Docker是现在最流行的容器化技术很多项目都在用Docker部署但是当应用需要多个容器的时候比如Web应用需要NginxPHPMySQLRedis等等多个容器手动一个个启动管理就很麻烦这时候就需要Docker Compose了。

Docker Compose是Docker官方的编排工具能用一个配置文件定义和管理多个容器一键启动停止重建整个应用非常方便我用Docker Compose已经有一段时间了部署了很多项目踩了很多坑也总结了很多经验今天就来分享一下Docker Compose的实战经验。

一、Docker Compose简介

Docker Compose是Docker官方的容器编排工具前身是Fig后来被Docker收购改名为Docker Compose它能让你用一个YAML配置文件来定义多个容器的应用然后用一条命令就能启动所有的容器非常方便。

Docker Compose的核心是docker-compose.yml文件在这个文件里你可以定义应用需要的所有服务(容器)包括镜像端口环境变量数据卷依赖关系网络等等然后用docker-compose up命令就能一键启动所有的服务用docker-compose down就能一键停止并删除所有的服务非常方便。

Docker Compose适合开发测试和小规模生产环境对于大规模的生产集群可能需要用Kubernetes等等更强大的编排工具但是对于大部分中小项目Docker Compose完全够用而且简单易用很方便。

二、安装Docker Compose

Docker Compose的安装很简单如果你安装的是Docker Desktop(Windows/Mac)那么Docker Compose已经自带了不用单独安装。

如果是Linux系统可以用以下命令安装:

# 下载Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

安装完成后用docker-compose --version命令能看到版本号就说明安装成功了。

三、docker-compose.yml基础

docker-compose.yml是Docker Compose的核心配置文件用YAML格式编写下面是一个简单的例子:

version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
  php:
    image: php:7.4-fpm
    volumes:
      - ./html:/var/www/html
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test
    volumes:
      - ./mysql:/var/lib/mysql

这个配置文件定义了三个服务:web(Nginx)php(PHP-FPM)mysql(MySQL)每个服务都配置了镜像端口环境变量数据卷等等。

下面介绍一下常用的配置项:

1. version

指定Docker Compose的版本现在一般用'3'或者'3.8'等等不同的版本支持的功能不同一般用最新的版本就行。

2. services

定义应用的所有服务每个服务就是一个容器下面是每个服务的配置。

3. image

指定服务使用的镜像比如nginx:latestphp:7.4-fpmmysql:5.7等等如果本地没有这个镜像Docker Compose会自动拉取。

4. build

如果不用现成的镜像而是要自己构建镜像可以用build指定Dockerfile所在的目录比如:

web:
  build: ./web

这样Docker Compose会在./web目录下找Dockerfile构建镜像。

5. ports

指定端口映射格式是"主机端口:容器端口"比如"80:80"就是把主机的80端口映射到容器的80端口这样访问主机的80端口就能访问到容器的80端口了。

6. volumes

指定数据卷映射格式是"主机路径:容器路径"比如"./html:/usr/share/nginx/html"就是把主机的./html目录挂载到容器的/usr/share/nginx/html目录这样容器里的这个目录的内容就和主机的目录同步了数据不会因为容器删除而丢失。

也可以用命名数据卷比如:

volumes:
  - mysql_data:/var/lib/mysql
volumes:
  mysql_data:

这样Docker会创建一个命名的数据卷用来持久化数据。

7. environment

指定环境变量用来给容器传递配置比如MySQL的root密码数据库名等等:

environment:
  MYSQL_ROOT_PASSWORD: root
  MYSQL_DATABASE: test

也可以用env_file从文件读取环境变量:

env_file:
  - .env

8. depends_on

指定服务的依赖关系比如web服务依赖mysql服务那么Docker Compose会先启动mysql再启动web:

web:
  depends_on:
    - mysql

注意depends_on只是保证启动顺序不会等待mysql完全就绪才启动web如果需要等待服务就绪需要用其他方式比如wait-for-it脚本等等。

9. networks

指定服务连接的网络Docker Compose会默认创建一个网络所有服务都在这个网络里能互相访问用服务名作为主机名就能互相访问比如web服务能用mysql:3306访问mysql服务。

也可以自定义网络:

services:
  web:
    networks:
      - frontend
      - backend
networks:
  frontend:
  backend:

10. restart

指定容器的重启策略比如always就是容器退出了总是重启适合生产环境:

restart: always

常用的重启策略有:no(不重启默认)always(总是重启)on-failure(失败时重启)unless-stopped(除非手动停止否则重启)。

四、常用命令

Docker Compose的常用命令有以下这些:

1. docker-compose up

启动所有服务这是最常用的命令加上-d参数能在后台运行:

docker-compose up -d

如果镜像不存在会自动拉取或者构建如果配置文件改了加上--build参数会重新构建镜像。

2. docker-compose down

停止并删除所有服务包括容器网络等等数据卷默认不会删除如果要删除数据卷加上-v参数:

docker-compose down
docker-compose down -v  # 同时删除数据卷

3. docker-compose ps

查看所有服务的运行状态:

docker-compose ps

4. docker-compose logs

查看服务的日志加上-f参数能实时查看日志:

docker-compose logs
docker-compose logs -f web  # 查看web服务的日志

5. docker-compose exec

在运行中的容器里执行命令比如进入mysql容器执行mysql命令:

docker-compose exec mysql mysql -u root -p

6. docker-compose restart

重启所有服务或者指定的服务:

docker-compose restart
docker-compose restart web  # 只重启web服务

7. docker-compose pull

拉取所有服务的镜像:

docker-compose pull

8. docker-compose build

构建所有服务的镜像:

docker-compose build

五、实战案例:部署LNMP环境

下面用一个实战案例来演示怎么用Docker Compose部署LNMP(Linux + Nginx + MySQL + PHP)环境。

首先创建项目目录结构:

lnmp/
├── docker-compose.yml
├── nginx/
│   └── default.conf
├── php/
│   └── Dockerfile
├── mysql/
│   └── data/  # MySQL数据目录
└── www/
    └── index.php  # 网站根目录

然后编写docker-compose.yml:

version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./www:/usr/share/nginx/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
    restart: always
    networks:
      - lnmp

  php:
    build: ./php
    volumes:
      - ./www:/var/www/html
    depends_on:
      - mysql
    restart: always
    networks:
      - lnmp

  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test
    volumes:
      - ./mysql/data:/var/lib/mysql
    restart: always
    networks:
      - lnmp

networks:
  lnmp:

然后编写nginx/default.conf:

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
        include fastcgi_params;
    }
}

然后编写php/Dockerfile:

FROM php:7.4-fpm
RUN docker-php-ext-install pdo pdo_mysql mysqli

然后在www目录下创建index.php:

<?php
phpinfo();

最后启动服务:

docker-compose up -d

启动完成后访问http://localhost就能看到phpinfo页面了说明LNMP环境部署成功了。

用docker-compose ps能查看服务状态用docker-compose logs能查看日志用docker-compose exec mysql mysql -u root -p能进入MySQL很方便。

六、最佳实践和注意事项

1. 数据持久化

重要的数据一定要用数据卷持久化比如MySQL的数据上传的文件等等不要把数据存在容器里否则容器删除了数据就丢了。

2. 环境变量配置

敏感的配置比如数据库密码API密钥等等不要硬编码在docker-compose.yml里要用环境变量或者.env文件而且.env文件不要提交到Git仓库要加入.gitignore。

3. 镜像版本固定

不要用latest标签的镜像因为latest会变化可能导致不可预期的问题要固定镜像版本比如nginx:1.21php:7.4-fpmmysql:5.7等等这样能保证环境一致可复现。

4. 健康检查

对于重要的服务可以配置健康检查让Docker能自动检测服务是否正常不正常的话自动重启:

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 30s
  timeout: 10s
  retries: 3

5. 资源限制

可以给服务配置资源限制比如内存CPU限制避免某个服务占用太多资源影响其他服务:

deploy:
  resources:
    limits:
      cpus: '0.50'
      memory: 512M

注意这个需要Docker Compose版本3以上而且需要用docker stack deploy部署才生效或者用docker-compose也支持。

6. 不要在容器里存数据

容器是临时的随时可能被删除重建所以不要在容器里存重要的数据所有重要的数据都要挂载到主机或者数据卷里。

7. 一个容器一个进程

遵循一个容器一个进程的原则不要在一个容器里跑多个服务比如不要在一个容器里同时跑Nginx和PHP-FPM要分成两个容器这样更符合Docker的理念也更容易管理和扩展。

七、写在最后

Docker Compose实战:用编排工具管理多容器应用。

Docker Compose是一个非常好用的容器编排工具能让你用一个配置文件定义和管理多个容器一键启动停止重建整个应用非常方便对于开发测试和中小规模的生产环境都很适用。

这篇文章分享了Docker Compose的基础用法常用命令实战案例以及最佳实践和注意事项希望能帮大家更好地使用Docker Compose管理多容器应用。

当然Docker Compose也有它的局限性对于大规模的生产集群可能需要用Kubernetes等等更强大的编排工具但是对于大部分中小项目Docker Compose完全够用而且简单易用很值得学习和使用。

最后用一句话结尾:

"Docker Compose让多容器应用的管理变得简单高效是每个开发者和运维都应该掌握的工具。"

祝大家都能用好Docker Compose部署顺利!