一文吃透 Docker Compose:从概念语法到多容器一键部署实战
第9章 Docker-compose摘要本章详细介绍了 Docker Compose 这一多容器编排管理工具。首先解释了 Compose 的核心概念服务与项目及其工作原理然后展示了完整的命令说明和版本信息。重点讲解了 Compose 模板文件的结构和语法最后通过 WordPress 博客系统的实战案例对比了传统docker run方式与 Compose 方式的部署差异演示了如何使用docker-compose.yml文件一键启动和管理多个关联容器。续上篇博客 容器日志全解Docker 日志输出原理与 logs 命令实战我们知道使用一个Dockerfile模板文件可以让用户很方便的定义一个单独的应用容器。然而在日 常工作中经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目除了 Web 服务容器本身往往还需要再加上后端的数据库服务容器甚至还包括负载均衡容器等。如果每个 容器都要按顺序手动启停那么维护工作量将会很大而且工作效率也很低。Docker Compose 可以轻松、高效地管理容器它是一个用于定义和运行多容器的管理工具。它通过一个单独的docker-compose.yml模板文件YAML 格式定义一组相关联资源集。Compose中有两个重要的概念服务 (service)一个应用的容器实际上可以包括若干运行相同镜像的容器实例。项目 (project)由一组关联的应用容器组成的一个完整业务单元在docker-compose.yml文件中定义。Compose的默认管理对象是项目通过子命令对项目中的一组容器进行便捷地生命周期管理。Compose项目由 Python 编写(后用Go语言重写)实现上调用了 Docker 服务提供的 API 来对容器进行 管理。因此只要所操作的平台支持 Docker API就可以在其上利用Compose来进行编排管理。命令说明[rootdocker ~]# docker compose -hFlag shorthand-hhas been deprecated, please use--helpUsage:dockercompose[OPTIONS]COMMAND Define and run multi-container applications with Docker Options: --all-resources Include all resources, even those not used by services--ansistring Control when to print ANSI control characters(never|always|auto)(defaultauto)--compatibilityRun composeinbackward compatibility mode --dry-run Executecommandindry run mode --env-file stringArray Specify an alternate environmentfile-f,--filestringArray Compose configuration files--parallelint Control max parallelism,-1forunlimited(default -1)--profilestringArray Specify a profile toenable--progressstring Settypeof progress output(auto, tty, plain, quiet)(defaultauto)--project-directory string Specify an alternate working directory(default: the path of the, first specified, Composefile)-p, --project-name string Project name Commands: attach Attachlocalstandard input, output, and error streams to aservices running container build Build or rebuild services config Parse, resolve and render compose file in canonical format cp Copy files/folders between a service container and the local filesystem create Creates containers for a service down Stop and remove containers, networks events Receive real time events from containers exec Execute a command in a running container images List images used by the created containers kill Force stop service containers logs View output from containers ls List running compose projects pause Pause services port Print the public port for a port binding ps List containers pull Pull service images push Push service images restart Restart service containers rm Removes stopped service containers run Run a one-off command on a service scale Scale services start Start services stats Display a live stream of container(s) resource usage statistics stop Stop services top Display the running processes unpause Unpause services up Create and start containers version Show the Docker Compose version information wait Block until the first service container stops watch Watch build context for service and rebuild/refresh containers when files are updated Run dockercompose COMMAND --helpformoreinformation on a command.version[rootdocker ~]# docker compose versionDocker Compose version v2.27.0Compose 模板模板文件是使用Compose的核心涉及到的指令关键字也比较多。但大家不用担心这里面大部分指令 跟docker run相关参数的含义都是类似的。默认的模板文件名称为docker-compose.yml格式为YAML格式。模板文件结构version用来定义模板文件的版本不同版本的模板格式也不一样。资源列表用来定义资源清单包括service、secret、network、volume等。注释行#开头的注释行。示例使用版本2模板定义一个使用httpd镜像的services。version:2services: webapp: image: httpd详细结构参考官方 https://docs.docker.com实战-Wordpress回顾一下如果用docker run改如何操作:[rootdocker ~]# docker run -tid --name db --restart always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORDhuawei -e MYSQL_DATABASEwordpress mysqld3fa1d9e6ecc285427b38bca95130cade90ca69ee9487825db92b3bc8af4c995[rootdocker ~]# docker run -tid --name blog -v /web:/var/www/html -p 80:80 --link db -e WORDPRESS_DB_HOSTdb -e WORDPRESS_DB_USERroot -e WORDPRESS_DB_PASSWORDhuawei -e WORDPRESS_DB_NAMEwordpress wordpressb5b80bd69f57bff576415f2e449a23fe6cb37be353f9b4b69d24d60a2fb9a6e1[rootdocker ~]#[rootdocker ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b5b80bd69f57 wordpressdocker-entrypoint.s…13seconds ago Up12seconds0.0.0.0:80-80/tcp, :::80-80/tcp blog d3fa1d9e6ecc mysqldocker-entrypoint.s…26seconds ago Up25seconds3306/tcp,33060/tcp dbMYSQL_DATABASEwordpress测试效果:通过docker compose来统一管理这两个容器呢假设新建一个名为wordpress的文件夹然后进入这个文件夹创建docker-compose.yml文件# 删除之前的环境[rootdocker ~]# docker rm -f $(docker ps -aq)# 通过docker compose实现多个容器一起启动[rootdocker ~]# mkdir wordpress[rootdocker ~]# cd wordpress/[rootdocker wordpress]# vim docker-compose.ymlservices: blog:#服务名字相当于docker run的时候指定的一个名称image: wordpress:latest#必选镜像的名字restart: always links: - db ports:#可选等价于 docker run 里的 -p 选项指定端口映射-80:80environment:#可选等价于 docker run 里的 --env 选项设置环境变量-WORDPRESS_DB_HOSTdb -WORDPRESS_DB_USERroot -WORDPRESS_DB_PASSWORDhuawei -WORDPRESS_DB_NAMEwordpress db: image: mysql:latest restart: always environment: -MYSQL_ROOT_PASSWORDhuawei -MYSQL_DATABASEwordpress[rootdocker wordpress]# docker compose config -q #检测语法后端运行[rootdocker wordpress]# docker compose up -d[]Running3/3 ✔ Network wordpress_default Created0.0s ✔ Container wordpress-db-1 Started0.3s ✔ Container wordpress-blog-1 Started0.6s查看现象[rootdocker ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 85b438b2ff89 wordpress:latestdocker-entrypoint.s…About a minute ago Up About a minute0.0.0.0:80-80/tcp, :::80-80/tcp wordpress-blog-1 d3fa1d9e6ecc mysql:latestdocker-entrypoint.s…About a minute ago Up About a minute3306/tcp,33060/tcp wordpress-db-1docker compose 实战[rootdocker ~]# mkdir porject[rootdocker ~]# cd project/[rootdocker project]# vim docker-compose.yml# 自定义网络所有服务同网段networks: web-net: driver: bridge# 数据卷持久化volumes: mysql-data: nginx-conf: services:# MySQL 数据库mysql: image: mysql:5.7 container_name: mysql-db restart: always environment: MYSQL_ROOT_PASSWORD:123456MYSQL_DATABASE: webdb MYSQL_USER: webuser MYSQL_PASSWORD: web123456 volumes: - mysql-data:/var/lib/mysql ports: -3306:3306networks: - web-net command: --default-authenticationpluginmysql_native_password# 后端网站1web1: image: nginx:alpine container_name: web-site1 restart: always networks: - web-net environment: DB_HOST: mysql-db DB_PORT:3306DB_NAME: webdb volumes: - ./site1:/usr/share/nginx/html# 后端网站2web2: image: nginx:alpine container_name: web-site2 restart: always networks: - web-net environment: DB_HOST: mysql-db DB_PORT:3306DB_NAME: webdb volumes: - ./site2:/usr/share/nginx/html# 后端网站3web3: image: nginx:alpine container_name: web-site3 restart: always networks: - web-net environment: DB_HOST: mysql-db DB_PORT:3306DB_NAME: webdb volumes: - ./site3:/usr/share/nginx/html# 前端Nginx负载均衡nginx-lb: image: nginx:alpine container_name: nginx-loadbalance restart: always ports: -80:80volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - nginx-conf:/etc/nginx/conf.d networks: - web-net depends_on: - web1 - web2 - web3 - mysql新建 Nginx 负载均衡配置[rootdocker project]# mkdir nginx[rootdocker project]# vim nginx/nginx.confuser nginx;worker_processes auto;error_log /var/log/nginx/error.log warn;pid /var/run/nginx.pid;events{worker_connections1024;}http{include /etc/nginx/mime.types;default_type application/octet-stream;# 定义后端服务器集群upstream web_server_pool{server web-site1:80weight1;server web-site2:80weight2;server web-site3:80weight3;}server{listen80;server_name localhost;location /{proxy_pass http://web_server_pool;proxy_set_header Host$host;proxy_set_header X-Real-IP$remote_addr;proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;}}}准备网站首页内容[rootdocker project]# mkdir site1 site2 site3[rootdocker project]# echo site1 site1/index.html[rootdocker project]# echo site2 site2/index.html[rootdocker project]# echo site3 site3/index.html检查[rootdocker project]# tree.├── docker-compose.yml ├── nginx │ └── nginx.conf ├── site1 │ └── index.html ├── site2 │ └── index.html └── site3 └── index.html4directories,5files[rootdocker project]# docker compose up -d测试[rootdocker project]# for n in {1..6}; do curl http://192.168.108.30 -s; done | sort |uniq -c1site12site23site3