使用 HEALTHCHECK 自定义方法实现
假设我们有一个Web应用,需要依赖于一个MySQL数据库。我们需要在MySQL数据库启动并进入ready状态后,才能启动Web应用。
首先,我们需要创建一个Dockerfile来定义MySQL数据库容器:
FROM mysql:5.7
# 设置环境变量
ENV MYSQL_DATABASE=mydb \
MYSQL_ROOT_PASSWORD=123456
# 添加健康检查脚本
COPY healthcheck.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/healthcheck.sh
HEALTHCHECK --interval=5s --timeout=3s \
CMD /usr/local/bin/healthcheck.sh || exit 1
上面的Dockerfile定义了一个MySQL数据库容器,设置了数据库名称和root用户密码,并添加了一个健康检查脚本healthcheck.sh
。该脚本会检查MySQL数据库是否已经启动并准备好接收请求,如果是则返回0,否则返回1。
健康检查脚本healthcheck.sh
的内容如下:
#!/bin/bash
if mysql -hlocalhost -uroot -p123456 -e "SELECT 1"; then
exit 0
else
exit 1
fi
该脚本会使用mysql
命令连接到MySQL数据库,并执行一个简单的SQL语句,如果连接成功则返回0,否则返回1。
接下来,我们需要创建一个Dockerfile来定义Web应用容器:
FROM node:10
# 设置工作目录
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm install
# 添加应用代码
COPY . .
# 添加健康检查脚本
COPY healthcheck.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/healthcheck.sh
HEALTHCHECK --interval=5s --timeout=3s \
CMD /usr/local/bin/healthcheck.sh || exit 1
# 启动应用
CMD ["npm", "start"]
上面的Dockerfile定义了一个Node.js应用容器,安装了应用依赖,并添加了一个健康检查脚本healthcheck.sh
。该脚本会检查应用是否已经启动并准备好接收请求,如果是则返回0,否则返回1。
最后,我们可以使用docker-compose
来启动这两个容器,定义如下的docker-compose.yml
文件:
version: "3"
services:
db:
build:
context: .
dockerfile: Dockerfile.db
ports:
- "3306:3306"
app:
build:
context: .
dockerfile: Dockerfile.app
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
上面的docker-compose.yml
文件定义了两个服务db
和app
,分别对应MySQL数据库容器和Web应用容器。db
服务的Dockerfile文件名为Dockerfile.db
,app
服务的Dockerfile文件名为Dockerfile.app
。
在app
服务中,我们使用了depends_on
参数来指定依赖关系。condition: service_healthy
表示只有当db
服务进入健康状态后,才会启动app
服务。
现在,我们可以使用docker-compose up
命令启动这两个容器:
$ docker-compose up
Docker会先启动db
服务,等待MySQL数据库进入ready状态后,再启动app
服务。这样,我们就实现了在MySQL数据库启动并进入ready状态后,才启动Web应用的需求。
下面是使用wait-for的方式实现
它需要在数据库启动之后才能启动。我们可以使用wait-for来等待数据库启动完成后再启动Web应用程序。
首先,我们需要在Dockerfile中添加wait-for脚本:
FROM node:12
# 安装wait-for脚本
ADD https://github.com/eficode/wait-for/raw/master/wait-for /usr/local/bin/wait-for
RUN chmod +x /usr/local/bin/wait-for
# 拷贝应用程序代码
WORKDIR /app
COPY . .
# 安装依赖
RUN npm install
# 暴露端口
EXPOSE 3000
# 启动应用程序
CMD ["wait-for", "db:5432", "--", "npm", "start"]
在Dockerfile中,我们下载了wait-for脚本,并将其添加到容器中的/usr/local/bin目录。然后,我们拷贝应用程序代码到工作目录/app中,并安装依赖。最后,我们暴露端口并使用wait-for脚本等待数据库启动完成后再启动应用程序。
接下来,在docker-compose.yml中定义服务:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres
在docker-compose.yml中,我们定义了两个服务:web和db。web服务依赖于db服务。这意味着在启动web服务之前,docker-compose会先启动db服务。
最后,在应用程序中,我们可以使用以下命令来连接数据库:
const { Pool } = require('pg');
const pool = new Pool({
host: 'db',
port: 5432,
database: 'mydatabase',
user: 'myuser',
password: 'mypassword',
});
pool.query('SELECT NOW()', (err, res) => {
console.log(err, res);
pool.end();
});
在应用程序中,我们使用了pg库来连接数据库。我们将host设置为db,这是docker-compose.yml文件中定义的db服务的名称。这样,当我们使用wait-for脚本等待数据库启动完成后,我们就可以成功连接到数据库了。