如何使用 Docker Compose 在单台服务器上高效部署多个 Docker 容器项目

2024年4月14日
Share

前言

在今天高效率的IT领域,Docker 和 Docker Compose 已成为开发者和系统管理员不可或缺的工具。它们不仅加速了部署过程,还通过容器化技术简化了复杂应用的管理。本文将深入探讨如何利用 Docker Compose 在单台服务器上快速且高效地部署和管理多个项目,这对于希望优化资源使用和简化操作流程的业务来说,具有不小的吸引力。这里我也会把自己在实践中遇到的几个容易出错的地方和大家分享,自己也加深影响,避免再次犯错!

利用 Docker Compose 快速部署项目的优势

Docker Compose 允许用户通过单一命令行工具管理多个 Docker 容器的生命周期,具体优势包括:

  1. 配置简便:Docker Compose 允许您在 YAML 文件中定义多服务配置,从而简化了 Docker 容器的配置和部署过程。
  2. 一键控制:可以通过一个命令同时管理多个容器的启动、停止和重建,极大地提高了操作的便捷性。
  3. 服务依赖清晰:Docker Compose 自动处理容器之间的依赖关系,确保服务按正确顺序启动。
  4. 环境一致性:通过 Docker Compose,每个项目都在独立的环境中运行,确保了环境之间的隔离,减少了冲突。

在实际部署前,请准备好一台vps,我这里使用的是 甲骨云 arm结构的虚拟主机。

这里我将同时部署 5个 wordpress 项目,搭配PHP环境,redis 缓存加速,mysql 数据库还有 npm反向代理,来实现多个docker 容器项目的同时部署。

WordPress 服务示例wp1):

    wp1:
    image: 'arm64v8/wordpress'     //注意这里要选择适合自己架构的镜像版本,我这边是arm64
    container_name: wp1            //定义容器的名字
    volumes:
      - ./html1:/var/www/html     //这里使用html1,作为容器储存数据的数据卷
    ports:
      - '8081:80'
    environment:
      WORDPRESS_DB_HOST: ${WP1_DB_HOST}           //主机名,最好和数据库名不要重复,容易报错
      WORDPRESS_DB_USER: ${WP1_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WP1_DB_PASSWORD}
      WORDPRESS_DB_NAME: ${MYSQL1_DATABASE}         //这里是我踩过的坑,遗漏了DB_NAME,导致wp-config 读取不到数据库,访问的时候出现无法连接数据库的提示
    depends_on:                                     //定义容器启动顺序
      - db1
      - redis
    networks:
      - web1                                      //定义容器的网络
    

    如果是多个WordPress 服务,就按照上面的模版复制,写入conpose文件

    数据库 配置

      db1:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql1
        restart: unless-stopped
        volumes:
          - ./mysql1:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL1_ROOT_PASSWORD}
          MYSQL_DATABASE: {MYSQL1_DATABASE}
          MYSQL_USER: ${MYSQL1_USER} 
          MYSQL_PASSWORD: ${MYSQL1_PASSWORD}
        ports:
          - '3307:3306'
        networks:
          - web1

    这边必须是一个wordpress 服务对应一个 数据库,我之前试过多个服务对应一个数据库,行不通

    最好贴上完整的compose 代码

    version: '3.9'
    
    services:
      php:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: php
        restart: always
        volumes:
          - ./html:/var/www/html
          - ./php.ini:/usr/local/etc/php/conf.d/php.ini
        ports:
          - '9000:9000'
        networks:
          - web1
      wp1:
        image: 'arm64v8/wordpress'
        container_name: wp1
        volumes:
          - ./html1:/var/www/html
        ports:
          - '8081:80'
        environment:
          WORDPRESS_DB_HOST: ${WP1_DB_HOST}
          WORDPRESS_DB_USER: ${WP1_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WP1_DB_PASSWORD}
          WORDPRESS_DB_NAME: ${MYSQL1_DATABASE}
        depends_on:
          - db1
          - redis
        networks:
          - web1
      db1:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql1
        restart: unless-stopped
        volumes:
          - ./mysql1:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL1_ROOT_PASSWORD}
          MYSQL_DATABASE: {MYSQL1_DATABASE}
          MYSQL_USER: ${MYSQL1_USER} 
          MYSQL_PASSWORD: ${MYSQL1_PASSWORD}
        ports:
          - '3307:3306'
        networks:
          - web1
      wp2:
        image: 'arm64v8/wordpress'
        container_name: wp2
        volumes:
          - ./html2:/var/www/html
        ports:
          - '8082:80'
        environment:
          WORDPRESS_DB_HOST: ${WP2_DB_HOST}
          WORDPRESS_DB_USER: ${WP2_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WP2_DB_PASSWORD}
          WORDPRESS_DB_NAME: ${MYSQL2_DATABASE}
        depends_on:
          - db2
          - redis
        networks:
          - web1
      db2:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql2
        restart: unless-stopped
        volumes:
          - ./mysql2:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL2_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL2_DATABASE}
          MYSQL_USER: ${MYSQL2_USER}
          MYSQL_PASSWORD: ${MYSQL2_PASSWORD}
        ports:
          - '3308:3306'
        networks:
          - web1
      wp3:
        image: 'arm64v8/wordpress'
        container_name: wp3
        volumes:
          - ./html3:/var/www/html
        ports:
          - '8083:80'
        environment:
          WORDPRESS_DB_HOST: ${WP3_DB_HOST}
          WORDPRESS_DB_USER: ${WP3_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WP3_DB_PASSWORD}
          WORDPRESS_DB_NAME: ${MYSQL3_DATABASE}
        depends_on:
          - db3
          - redis
        networks:
          - web1
      db3:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql3
        restart: unless-stopped
        volumes:
          - ./mysql3:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL3_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL3_DATABASE}
          MYSQL_USER: ${MYSQL3_USER}
          MYSQL_PASSWORD: ${MYSQL3_PASSWORD}
        ports:
          - '3309:3306'
        networks:
          - web1
      wp4:
        image: 'arm64v8/wordpress'
        container_name: wp4
        volumes:
          - ./html4:/var/www/html
        ports:
          - '8084:80'
        environment:
          WORDPRESS_DB_HOST: ${WP4_DB_HOST}
          WORDPRESS_DB_USER: ${WP4_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WP4_DB_PASSWORD}
          WORDPRESS_DB_NAME: ${MYSQL4_DATABASE}
        depends_on:
          - db4
          - redis
        networks:
          - web1
      db4:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql4
        restart: unless-stopped
        volumes:
          - ./mysql4:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL4_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL4_DATABASE}
          MYSQL_USER: ${MYSQL4_USER}
          MYSQL_PASSWORD: ${MYSQL4_PASSWORD}
        ports:
          - '3310:3306'
        networks:
          - web1
      wp5:
        image: 'arm64v8/wordpress'
        container_name: wp5
        volumes:
          - ./html5:/var/www/html
        ports:
          - '8085:80'
        environment:
          WORDPRESS_DB_HOST: ${WP5_DB_HOST}
          WORDPRESS_DB_USER: ${WP5_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WP5_DB_PASSWORD}
          WORDPRESS_DB_NAME: ${MYSQL5_DATABASE}
        depends_on:
          - db5
          - redis
        networks:
          - web1
      db5:
        image: 'mysql/mysql-server:8.0.13'
        container_name: mysql5
        restart: unless-stopped
        volumes:
          - ./mysql5:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL5_ROOT_PASSWORD}
          MYSQL_DATABASE: ${MYSQL5_DATABASE}
          MYSQL_USER: ${MYSQL5_USER}
          MYSQL_PASSWORD: ${MYSQL5_PASSWORD}
        ports:
          - '3311:3306'
        networks:
          - web1
      redis:
        image: 'redis:alpine'
        container_name: redis
        restart: unless-stopped
        volumes:
          - ./redis-data:/data
        ports:
          - '6379:6379'
        networks:
          - web1
      nginx-proxy-manager:
        image: 'jc21/nginx-proxy-manager:latest'
        container_name: npm
        restart: always
        ports:
          - '80:80'
          - '81:81'
          - '443:443' 
        volumes:
          - ./npm-data:/data
          - ./letsencrypt:/etc/letsencrypt
        networks:
          - web1
    networks:
      web1:
        driver: bridge
    

    环境变量 .env的部分代码,有几个服务项就编写几个环境变量,也可以统一,这里的变量值要和compose配置文件对应。容易出错的地方

    # For WordPress 1
    WP1_DB_HOST=hostname
    WP1_DB_USER=username
    WP1_DB_PASSWORD=youpassword
    
    # For MySQL 1
    MYSQL1_ROOT_PASSWORD=youpassword
    MYSQL1_DATABASE=databasename
    MYSQL1_USER=username
    MYSQL1_PASSWORD=youpassword

    使用 Docker Compose 来部署和管理服务器上的多个项目可以显著提高开发和部署的效率,同时也使得服务管理变得更加集中和简化。