使用Docker来容纳应用程序时,通常的做法是在单独的容器中运行应用程序的每个组件。例如,一个网站可能有一个Web服务器,应用程序和数据库,每个都在自己的容器中运行。
配置容器以相互通信和主机可能是一个挑战。本指南将使用一个简单的示例应用程序来演示Docker容器通信的基础知识。该应用程序将包含一个Node.js应用程序,该应用程序从PostgreSQL数据库中读取数据。
您需要安装带有Docker CE的Linode才能按照本指南中的步骤操作。
这些步骤使用官方Ubuntu存储库安装Docker Community Edition(CE)。要在其他发行版上安装,请参阅官方安装页面。
stable
Docker库:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"docker
组:
sudo usermod -aG docker exampleuser
需要重新启动shell会话才能使此更改生效。本指南中使用的示例应用程序将是一个简单的Node.js应用程序,它将从PostgreSQL数据库中读取“Hello world”并将其打印到控制台。在本节中,您将在不使用容器的情况下在Linode上构建和测试应用程序。
postgres
用户密码:
sudo passwd postgrespostgres
数据库用户设置密码:
su - postgres psql -d template1 -c "ALTER USER postgres WITH PASSWORD 'newpassword';"postgres
Linux用户:
exit/etc/postgresql/9.5/main/postgresql.conf
。取消注释行--listen_addresses,
并将其设置为“*”:
# /etc/postgresql/9.5/main/postgresql.conf
#------------------------------------------------------------------------------#CONNECTIONS AND AUTHENTICATION
#--------------------------------------
listen_addresses = '*' 设置被监听地址postgresql
服务:
sudo systemctl enable postgresql sudo systemctl start postgresqlapp.js
并添加以下内容:
const { Client } = require('pg')
const client = new Client({
user: 'postgres',
host: 'localhost',
database: 'nodejs',
password: 'newpassword',
port: 5432
})
client.connect()
client.query('SELECT * FROM hello', (err, res) => {
console.log(res.rows[0].message)
client.end()
})此应用程序使用pg
NPM模块(node-postgres)连接到上一节中创建的数据库。然后查询'hello'表(返回“Hello world”消息)并将响应记录到控制台。把'newpassword'替换
为postgres
您在上一节中设置的数据库用户密码。
注意该pg
模块还可以使用环境变量来配置客户端连接。这是生产应用程序的推荐选项。在node-postgres文档中阅读有关环境变量的更多信息。
pg
模块:
npm install pg本节说明了Node.js应用程序从Docker容器运行并连接到Docker主机上运行的数据库的用例。
app/
目录下。编辑app.js
以允许应用程序连接到database
主机而不是localhost
:
# app/ app.js
const client = new Client({
user: 'postgres',
host: 'database',
database: 'nodejs',
password: 'newpassword',
port: 5432
})docker0
。使用ifconfig
或ip
查看此界面:
ifconfig docker0
输出将类似于以下内容:
docker0 Link encap:Ethernet HWaddr 02:42:1e:e8:39:54 inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:1eff:fee8:3954/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3848 errors:0 dropped:0 overruns:0 frame:0 TX packets:5084 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:246416 (246.4 KB) TX bytes:94809688 (94.8 MB)
Docker主机(你的Linode)的内部IP地址是172.17.0.1。
/etc/postgresql/9.5/main/pg_hba.conf
在文本编辑器中打开并添加以下行:
# /etc/postgresql/9.5/main/pg_hba.conf1
host all postgres 172.17.0.0/16 password
由于172.17.0.1是Docker主机的IP,因此主机上的所有容器都将具有172.17.0.0/16网段内的IP地址。--add-host
选项定义了一个database
主机,它指向Docker主机的IP地址。database
在运行时声明主机,而不是硬编码应用程序中的IP地址,有助于保持容器可重用。ping
测试与database
主机的连接:
docker exec -it node_container ping databaseip
:
docker exec -it node_container ip addr show eth0
你可以通过从Docker主机ping该地址来测试此连接。如果配置成功,你将在控制台看见“Hello world”。
在本节中,应用程序和数据库将在不同的容器中运行。您可以使用Docker Hub中的官方postgres镜像并加载之前创建的SQL。
特别说明:您不应将生产数据库数据存储在Docker容器中。应将容器视为临时实体:如果容器意外崩溃或重新启动,则数据库中的所有数据都将丢失。
postgres
镜像:
docker pull postgresbackup.sql
文件位于当前工作目录中,然后运行postgres
镜像:
docker run -d -v `pwd`:/backup/ --name pg_container postgres
-v
选项将当前工作目录安装到/backup/
新容器上的目录中。--add-host选项,而使用--link
选项将容器连接到pg_container:
docker run -d --name node_container --link=pg_container:database node_image
该命令将链接pg_container
主机名下database
。pg_container
已分配给IP地址172.17.0.2,并按database
预期通过主机名连接到此容器。database
主机上的PostgreSQL数据库,因此无需进一步更改。你应该能够像以前一样运行应用程序:
docker exec -it node_container node home/app.js每次启动容器时使用--link
或--host
选项都很麻烦。如果您的服务器或任何容器崩溃,则必须手动重新连接。对于需要持续可用性的任何应用程序而言,这不是理想情况。幸运的是,Docker提供了Docker Compose来管理多个容器,并在启动时自动将它们链接在一起。本节将使用Docker Compose重现上一节的结果。
注意:有关Docker Compose以及如何编写
docker-compose.yml
配置文件的更全面说明,请参阅完整的Docker Compose指南。
docker-compose.yml
包含以下内容的文件:
#docker-compose.yml
version: '3'
services:
database:
image: postgres
container_name: pg_container
volumes:
- pgdata:/var/lib/postgresql/data
app:
build: .
container_name: node_container
links:
- database
environment:
- PGPASSWORD=newpassword
- PGUSER=postgres
- PGDATABASE=nodejs
- PGHOST=database
- PGPORT=5432
depends_on:
- database
volumes:
pgdata: {} 当你使用此文件运行Docker Compose时,它将从上一会话中创建pg_container
和node_container
。和之前一样,数据库容器将使用官方PostgreSQL镜像,而app容器将从Dockerfile构建。该links
条目与前面使用--link
的run
命令中的选项具有相同的功能。
app.js
以删除这些值:
# app.js
const express = require('express')
const { Client } = require('pg')
const client = new Client()
client.connect()
client.query('SELECT * FROM hello', (err, res) => {
console.log(res.rows[0].message)
client.end()
})app.js
从app容器运行:
docker exec -it node_container node home/app.js该应用程序应该像以前一样运行
默认情况下,Docker会自动为每个容器和Docker主机分配IP地址。您可以使用这些地址手动连接容器之间的服务(假设您的防火墙允许连接)。
但是,Docker还为这些连接提供了许多方便的包装器,以帮助您加速和简化连接过程。您可以将Docker主机连接到具有唯一主机名的容器,或直接链接两个容器。使用Docker Compose可以进一步简化此过程,允许您在docker-compose.yml
文件中声明连接,以便在启动容器时自动建立连接。
本指南中未介绍其他连接选项。例如,您可以运行容器--net="host"
,它将与Docker主机共享该容器的网络堆栈:localhost
容器上将指向localhost
Docker主机。您还可以在每个Docker容器上公开端口,或配置默认桥接网络以获得更大的灵活性。有关这些选项的更深入讨论,请参阅下面“更多信息”部分中的链接。
有关此主题的其他信息,您可能需要参考以下资源。虽然提供这些是希望它们有用,但请注意,我们无法保证外部托管材料的准确性或及时性。