著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
为什么要有Docker Compose多容器部署
为了多快好省,总结起来就是为了偷懒,如图所示,一个 dockerfile 文件可以启动多个容器
在使用 docker Compose之前,我们是怎么部署多个容器的APP应用的呢???
- 使用
docker build -t [imageName]:[tag] .
命令或者docker pull [imageName]
从Dockerhub 拉取镜像 docker run
创建启动多个container- 依次管理这些container(启动停止删除)
多容器部署的APP太恶心了(每次都重复这么多步骤)
docker Compose到底是什么
- Docker Compose 是一个命令行工具
- 这个工具可以通过一个yml文件定义多个容器的docker应用
- 通过一条命令就可以根据yml文件的定义去创建或者管理这些容器
docker yml 文件有一个默认的名字叫docker-compose.yml,其中有三个重要的概念:
- Services
- Networks
- Volumes
Services
- 一个Services代表一个 container,这个 container 可以从 dockerhub registory 的 image 来创建,或者从本地的 Dockerfile build 出来的 image 来创建
- Service的启动类似
docker run
命令,我们可以给其指定network
和volume
,所以可以给 service 指定network
和Volume
的语法
#docker-compose.yml文件内容示例 services: db: #APP NAME images:postgres:9.4 #使用的镜像 volumes: #数据卷映射名为db-data - "db-data:/var/lib/postgresql/data" networks: #docker network 使用back-tier - back-tier
以上内容等同于:
docker run -d --name db --network back-tier -v db-data:/var/lib/postgresql/data postgres:9.4
Volumes
Networks
接下来看一个实际的应用例子
version: '3' #docke compose版本 services: wordpress: #App name image: wordpress #使用镜像 ports: #端口映射 - 8080:80 environment: #容器环境变量配置 WORDPRESS_DB_HOST: mysql WORDPRESS_DB_PASSWORD: root networks: # docker 网卡 - my-bridge mysql: image: mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: wordpress volumes: #数据卷名mysql-data,对应备份容器中/var/lib/mysql所有内容 - mysql-data:/var/lib/mysql networks: - my-bridge volumes: #声明 mysql-data: networks: #声明 my-bridge: driver: bridge # 使用drive为bridge
Docker Compose 的安装
具体安装过程可以参考:docker docs-安装Docker Compose
Docker 水平扩展和负载均衡
# 以后台方式启动运行 docker-compose up -d # 查看启动的服务容器 docker-compose ps # 帮助指令 docker-compose up --help # 停止所有运行中的容器 docker-compose down # 构建镜像 docker-compose build
以下面这个 docker-compose.yml 文件为例:
version: "3" services: redis: image: redis web: build: context: ./dir dockerfile: Dockerfile ports: - 8080:5000 environment: REDIS_HOST: redis
context
:是 Dockerfile 的文件路径,也可以是链接到 git 仓库的 url 当提供的值是相对路径时,它被解析为相对于撰写文件的路径,此目录也是发送到 Docker 守护进程的 context
dockerfile
参数:dockerfile文件,必须指定的文件构建路径
scale
参数可以把一个服务扩展成多个,但是如果用上面这个文件启动的话
docker-compose up --scale web=3 -d
,会发现报错:
RROR : for flaskredis _ web _3 Cannot start service web : driver failed programming external connectivity on ndpoint flaskredis _ web _3(f2aea3a19f5a6f3eb949436293815da88d327228ff791390f9335e56acce9966): Bind for 0.0 0.0:8080-f8ed:79popeeots already alloCated RROR : for web Cannot start service web : driver failed programming external cqnnecttvtty on endipotnt fias redis _ web _2(a99bb015ed96780630baf05e42f65e13676be9faca695602b3eb228f108c445f): Bind for 0.0.0.0:8080 fai ed : port is already allocated RROR : Encountered errors while bringing up the project . flask - redis git :( master ) x docker - compose down topping flaskredis _ web _1 topping flaskredis _ redis _1 emoving flaskredis _ web _3 nnoncuah 7 done done done
-- exit - code - from SERVICE Return the exit code of the selected service container . Implies -- abort - on - container - exit . -- scale SERVICE = NUM Scale SERVIcE to NUM instances . Overrides the scale ~ setting in the compose file if present .
原因是因为ports: - 8080:5000
重复绑定,端口占用了,删除这条语句即可,表示不指定宿主机端口绑定。如下图启动成功:
→ flask - redis git :( master ) x docker - compose up flaskredis _ redis _1 is up - to - date Starting flaskredis _ web _1... done Creating flaskredis _ web _2... done Creating flaskredis _ web _3.. done flask - redis git :( master ) flask - redis git :( master ) -- scale web =3- d docker - compose ps Name command State Ports flaskredis _ rediS _1 flaskredisweb _1 flaskredis _ web _2 flaskredis _ web _3 docker - entrypoint . sh redis ... python app . py python app . py python app . py Up Up Up Up 6379/tcp 5000/tcp 5000/tcp 5000/tcp
来看一个负载均衡的例子
# Dockerfile FROM python:2.7 LABEL maintaner="Peng Xiao xiaoquwl@gmail.com" COPY . /app WORKDIR /app RUN pip install flask redis EXPOSE 80 CMD [ "python", "app.py" ]
#docker-compose.yml version: "3" services: redis: image: redis web: build: #指定的镜像需要build context: . #build的路径 dockerfile: Dockerfile #要build的dockerfile文件名(上面的文件) environment: REDIS_HOST: redis lb: image: dockercloud/haproxy #负载均衡的镜像 links: #连接到上面的service名为web的App - web ports: - 8080:80 volumes: - /var/run/docker.sock:/var/run/docker.sock
结构调用图
> lb - scale git :( master ) x docker - compose up -- scale web =3- d lbscale _ redis _ l is up - to - date Starting Tbscale _ web _1... done Creating lbscale _ web _2... done Creating lbscale _ web _3... done lbscale _ lb _1 is up - to - date lb - scale gt :( maSter x docker - compose ps command State Ports Namle Lbscale _ lb _1 / sbin / tini -- dockercloud - Lbscale _ redis _1 docker - entrypoint . sh redis ... lbscale _ web _1 python app . py ibscale _ web _2 python app . py Lbscale _ web _3 python app . py → lb - scale git :( master ) x curl 127.0.0.1:8080 Hello Container World ! I have been seen 2 times and my hostname is -> lb - scale git :( master ) x curl 127.0.0.1:8080 Hello Container World ! I have been seen 3 times and my hostname is → lb - scale git :( master ) x cur1127.0.0.1:8080 Hello Container World ! I have been seen 4 times and my hostname is -→ Tb - scale git :( master ) x curl 127.0.0.1:8080 -. 1936/tcp,443/tcp,0.0.0.0:8 6379/tcp 80/tcp 80/tcp 8o/ tcp Up Up Up D 068a6ee30234. 745ba7f91665. 63a35d2a9bef.
实践-部署一个复杂的Application
Voting App 用于投票,redids Queue用来保存投票结果,Java worker实时获取redis 中的数据插入PG database数据库中,Result app 实时从PG database中获取数据展示到页面。
这里涉及了5个docker容器,看到这里,你觉得应该怎么实现呢?这就当做一个练习给你们了,完成了的读者可以在下方评论留言,公布自己的docker-compose.yml
内容
更多内容参考=>docker-compose.yml 配置文件详解及项目发布