如何将Web服务与数据库作为单个镜像推送至Docker Registry?
问题:Docker Compose多服务部署后,其他机器无法自动拉取依赖的DB服务
我的环境配置
docker-compose.yml:
version: '3' services: db: image: mysql:5.7 environment: MYSQL_DATABASE: docker MYSQL_ROOT_PASSWORD: supersecret MYSQL_USER: superuser MYSQL_PASSWORD: supersecret DATABASE_HOST: db web: build: ./web image: jonas/testapp:2 links: - db ports: - "3333:3333" depends_on: - db restart: on-failure
web/Dockerfile:
FROM node:10.16.0 WORKDIR /usr/src/app COPY package.json /usr/src/app RUN npm install COPY . /usr/src/app EXPOSE 3333 CMD npm start
问题现象
- 本地执行
docker-compose up一切正常,MySQL镜像自动拉取,Web服务能正常连接DB - 执行
docker-compose push时,只有jonas/testapp:2被推送到我的镜像仓库 - 在其他机器执行
docker run -it -p 3333:3333 jonas/testapp:2,只能启动Web容器,无法获取DB服务,自然也没法连接
解决方案
首先得明确两个核心逻辑,搞懂了问题就迎刃而解:
docker-compose push只会推送你自定义的、带仓库地址的镜像(也就是你的jonas/testapp:2),官方的mysql:5.7不会被推送(也没必要,Docker Hub本来就有官方镜像)docker run是单容器运行命令,它完全不知道你本地docker-compose.yml里的DB服务配置,所以只会启动你指定的Web容器,不会自动帮你启动DB
下面是几种可行的解决方案,按推荐程度排序:
1. 在目标机器使用相同的docker-compose.yml(最推荐)
这是Docker Compose多服务部署的标准方式,步骤非常简单:
- 把你的
docker-compose.yml同步到目标机器(可以用Git、scp,或者把文件放到你的镜像仓库对应的代码库) - 在目标机器执行:
Compose会自动处理所有事情:docker-compose up -d- 检查
db服务的mysql:5.7镜像,如果本地没有,自动从Docker Hub拉取 - 检查
web服务的jonas/testapp:2镜像,如果本地没有,自动从你的私有仓库拉取(前提是目标机器已经docker login到你的仓库) - 自动创建服务间的网络、处理依赖顺序(比如先启动DB再启动Web)、配置环境变量,和你本地运行的效果完全一致
- 检查
2. 手动拉取镜像并启动(临时应急)
如果只是临时测试,不想同步docker-compose.yml,可以手动操作:
- 先在目标机器拉取MySQL镜像:
docker pull mysql:5.7 - 手动创建Docker网络(让Web和DB能互相访问):
docker network create app-network - 启动DB容器:
docker run -d \ --name db \ --network app-network \ -e MYSQL_DATABASE=docker \ -e MYSQL_ROOT_PASSWORD=supersecret \ -e MYSQL_USER=superuser \ -e MYSQL_PASSWORD=supersecret \ mysql:5.7 - 最后启动Web容器:
这种方式需要手动配置所有参数,非常繁琐,不适合生产环境。docker run -it \ --network app-network \ -e DATABASE_HOST=db \ -p 3333:3333 \ jonas/testapp:2
3. 不要尝试在单个容器里跑多个服务(强烈不推荐)
网上可能会有人建议用supervisord之类的工具在Web容器里同时跑Node和MySQL,但这违反了Docker一个容器一个进程的设计原则,会导致容器体积变大、难以维护、排查问题困难,完全不推荐。
额外注意事项
- 敏感信息(比如
MYSQL_ROOT_PASSWORD)不要硬编码在docker-compose.yml里,建议用.env文件管理,Compose会自动读取该文件的环境变量 - 如果你的私有仓库需要认证,目标机器必须先执行
docker login登录,才能拉取jonas/testapp:2镜像
内容的提问来源于stack exchange,提问作者wobsoriano
相关产品推荐
相关产品推荐

