问题描述
在使用docker-compose时遇到了问题:他想从一个node应用容器连接到一个postgres数据库容器,但在使用docker-compose后无法成功连接。以下是他的docker-compose.yml
文件:
version: '3.7'
services:
db:
image: postgres:12.1
ports:
- "5432:5432"
env_file:
- "./.env"
networks:
- tcp-modbus
volumes:
- ./modbustcp.sql:/docker-entrypoint-initdb.d/init.sql
redis:
image: redis:5.0.6
ports:
- "6379:6379"
networks:
- tcp-modbus
rabbit:
image: "rabbitmq"
environment:
RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
RABBITMQ_DEFAULT_USER: "*"
RABBITMQ_DEFAULT_PASS: "*"
RABBITMQ_DEFAULT_VHOST: "/"
ports:
- "15672:15672"
- "5672:5672"
volumes:
- "./enabled_plugins:/etc/rabbitmq/enabled_plugins"
networks:
- tcp-modbus
modbus-tcp:
image: customImage
ports:
- "8080:3000"
links:
- "db"
volumes:
- "./modbus.env:/usr/src/app/.env"
networks:
- tcp-modbus
networks:
tcp-modbus:
driver: bridge
他使用typeorm
来设置node应用的连接,但在docker化应用后,无法连接到postgresql容器。他猜测这可能与容器的主机名有关,因为他在连接postgresql容器时使用了localhost
。他想知道是否可以使用容器网络作为连接postgresql的主机名。
解决方案
请注意以下操作可能因版本差异而异,同时在开始操作前请做好备份。
使用docker-compose的内部DNS解决方案
在docker-compose中,每个服务都有一个内部DNS名。在你的示例中,服务的名称也是DNS名称。例如,数据库的DNS名是db
。如果在node应用中将其配置为主机名,那么应该能够访问数据库。
可以使用以下步骤来配置连接:
1. 在node应用中,将数据库主机名配置为db
。
2. 使用docker-compose构建和运行应用。
以下是一个示例的node应用配置:
const connectionOptions = {
type: "postgres",
host: "db", // 使用服务名称作为主机名
port: 5432,
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
synchronize: true,
logging: true,
entities: ["src/entities/**/*.ts"],
migrations: ["src/migrations/**/*.ts"],
subscribers: ["src/subscribers/**/*.ts"],
cli: {
entitiesDir: "src/entities",
migrationsDir: "src/migrations",
subscribersDir: "src/subscribers",
},
};
createConnection(connectionOptions)
.then(async (connection) => {
console.log("Connected to the database");
// Your app logic here
})
.catch((error) => console.log("Error: ", error));
这样,你的node应用将会使用服务名称db
作为主机名来连接到postgres数据库容器。
确保容器启动顺序
你提到在应用容器启动之前,其他服务容器已经启动。为了确保服务容器按照正确的顺序启动,你可以使用depends_on
标签。然而,你提到rabbit
容器在应用容器之后启动,可能是因为depends_on
并不能完全控制容器的启动顺序。
解决这个问题的一种方法是编写一个启动脚本,以确保容器按照正确的顺序启动。以下是一个示例的bash脚本,它可以在容器A启动后启动其他服务容器:
#!/bin/bash
# 启动数据库容器
docker-compose up -d db
# 等待数据库容器完全启动
while ! docker exec db pg_isready; do
sleep 1
done
# 启动其他服务容器
docker-compose up -d redis rabbit modbus-tcp
# 启动应用容器
docker-compose up -d node_app
在这个脚本中,我们首先使用docker-compose up -d db
命令启动数据库容器。然后,使用一个循环来等待数据库容器完全启动(这里是通过运行pg_isready
命令来测试)。一旦数据库容器就绪,我们再使用docker-compose up -d
命令依次启动其他服务容器和应用容器。
请根据你的实际情况进行调整和修改。这种方法确保了容器按照正确的顺序启动,从而解决了容器启动顺序的问题。
请注意,上述解决方案可能会因为Docker版本、Compose版本等因素而略有不同。请根据你的实际情况进行调整。