Dockercompose使用及举例

2023年 9月 7日 97.4k 0

一、简介

Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

Docker-Compose将所管理的容器分为三层,分别是:工程(project),服务(service)以及容器(container)。

Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。

一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡,比如 Consul。

Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。

使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。

在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API, 就可以在其上利用Compose来进行编排管理。

二、安装

Compose 支持 Linux、macOS、Windows 10 三大平台。

Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行。前两种方式是传统方式,适合本地环境下安装使用;最后一种方式则不破坏系统环境,更适合云计算场景。

Docker for MacDocker for Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用。运行以下指令检查是否安装成功:

$ docker-compose --version
​
docker-compose version 1.29.2, build b02f1306

Linux 系统请使用以下介绍的方法安装。

软件包方式安装

以ubuntu为例:

$ sudo apt install docker-compose

二进制包

在 Linux 上的也安装十分简单,从 官方 GitHub Release (opens new window) 处直接下载编译好的二进制文件即可。

例如,在 Linux 64 位系统上直接下载对应的二进制包, 这里下载的是1.29.2版本。大家根据情况更改这个版本。

$ sudo curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

PIP 安装

这种方式是将 Compose 当作一个 Python 应用来从 pip 源中安装。

执行安装命令:

$ sudo pip install -U docker-compose

注意:x86_64 架构的 Linux 建议按照上边的方法下载二进制包进行安装,如果您计算机的架构是 ARM (例如,树莓派),再使用 pip 安装。

卸载

如果是二进制包方式安装的,删除二进制文件即可。

$ sudo rm /usr/local/bin/docker-compose

如果是通过 pip 安装的,则执行如下命令即可删除。

$ sudo pip uninstall docker-compose

三、创建自定义网络

docker 容器的网络通信方式有多种,但是自定义网络最灵活,最有用,这里就只介绍自定义网络

1. 创建自定义网络

# 以桥接(bridge)方式,创建名称为docker_net的网络
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 docker_net

2. 查看网络

docker network ls

3. 启动容器,连接到自定义网络

3.1使用docker启动(以mysql为例)

# 运行mysql5.7,连到docker_net 这个自定义网络 
docker run -d -p 13306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 --net docker_net mysql:5.7

3.2使用docker-compose启动,见:二、docker-compose

4. 查看容器网络

# 还可以进入容器,ping宿主机或者其他容器
docker inspect 容器id

需要将已创建好的容器,连到某网路,也可以用 docker network connect 容器name 自定义网络name,如:

docker network connect mysql01 docker_net

四、使用docker-compose部署中间件

例:docker-compose -f docker-compose-mysql8.0.yml -p mysql8 up -d

-f:指定docker-compose.yml文件路径

-p:项目名称

-d:后台启动

portainer

docker-compose -f docker-compose-portainer.yml -p portainer up -d

version: '3'
services:
 portainer:
 image: registry.cn-hangzhou.aliyuncs.com/example/portainer:2.1.1
 container_name: portainer # 容器名为'portainer'
 restart: always # 指定容器退出后的重启策略为始终重启
 networks:
   docker_net:
     #服务在容器中ip(其他服务引用使用)
     ipv4_address: 172.22.16.2
 volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
   - ~/docker/portainer/data:/data
   - ~/docker/portainer/Portainer-CN:/public # 汉化
 environment: # 设置环境变量,相当于docker run命令中的-e
 TZ: Asia/Shanghai
 LANG: en_US.UTF-8
 ports: # 映射端口
 - "9001:9000"
networks:
 docker_net:
 external:
 name: docker_net
  • prometheus

  • version: "3"
    services:
      prometheus:
        image: registry.cn-hangzhou.aliyuncs.com/example/prometheus:2.30.0
        container_name: prometheus
        networks:
          docker_net:
            ipv4_address: 172.22.16.120
        volumes:
          - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
        command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus"
        ports:
          - "9090:9090"
        depends_on:
          - exporter
      exporter:
        image: registry.cn-hangzhou.aliyuncs.com/example/node-exporter:1.2.2
        container_name: prometheus_exporter
        ports:
          - "9100:9100"
        networks:
          docker_net:
            ipv4_address: 172.22.16.120
    
      # 用于UI展示
      # https://grafana.com/docs/grafana/latest/installation/docker
      grafana:
        image: registry.cn-hangzhou.aliyuncs.com/example/grafana:8.1.5
        container_name: prometheus_grafana
        restart: unless-stopped
        ports:
          - "3000:3000"
    #    volumes:
    #      - "./prometheus/grafana/grafana-storage:/var/lib/grafana"
    #      - "./prometheus/grafana/public:/usr/share/grafana/public" # 这里面可处理汉化包 可参考 https://github.com/WangHL0927/grafana-chinese
    #      - "./prometheus/grafana/conf:/usr/share/grafana/conf"
    #      - "./prometheus/grafana/log:/var/log/grafana"
    #      - "/etc/localtime:/etc/localtime"
        environment:
          GF_EXPLORE_ENABLED: "true"
          GF_SECURITY_ADMIN_PASSWORD: "admin"
          GF_INSTALL_PLUGINS: "grafana-clock-panel,grafana-simple-json-datasource,alexanderzobnin-zabbix-app"
          # 持久化到mysql数据库
          GF_DATABASE_URL: "mysql://root:123456:3306/grafana" # TODO 修改
        depends_on:
          - prometheus
        networks:
          docker_net:
            ipv4_address: 172.22.16.120
    networks:
      docker_net:
        external:
          name: docker_net
    

    mysql8

    docker-compose -f docker-compose-mysql8.0.yml -p mysql8 up -d

    version: '3'
    services:
      mysql:
        image: registry.cn-hangzhou.aliyuncs.com/example/mysql8:8.0.27
        container_name: mysql8  # 容器名为'mysql8'
        command:
        # MySQL8的密码验证方式默认是 caching_sha2_password,但是很多的连接工具还不支持该方式
        # 就需要手动设置下mysql的密码认证方式为以前的 mysql_native_password 方式
          --default-authentication-plugin=mysql_native_password
          --character-set-server=utf8mb4
          --collation-server=utf8mb4_general_ci
        restart: unless-stopped
        networks:
          docker_net:
            #服务在容器中ip(其他服务引用使用)
            ipv4_address: 172.22.16.80
        volumes:
          - ~/docker/mysql8/data:/var/lib/mysql
          - ~/docker/mysql8/conf:/etc/mysql/conf.d
          - ~/docker/mysql8/logs:/logs                                            
        environment:                        # 设置环境变量,相当于docker run命令中的-e
          TZ: Asia/Shanghai
          LANG: en_US.UTF-8
          MYSQL_ROOT_PASSWORD: 123456       # 设置root用户密码
        ports:                              # 映射端口
          - "3306:3306"
    networks:
      docker_net:
        external:
          name: docker_net
    

    错误:mysql连接错误 - is not allowed to connect to this my sql server

    解决方案如下:

    创建用户(创建root用户,可通过密码123456从任何主机登录)

    create user 'root'@'%' identified by  '123456';
    

    授予用户权限(授予该用户所有权限)

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
    

    3.刷新权限

    flush privileges;
    

    完成上述操作后,出现如下错误 authentication plugin ‘caching_sha2_password’ cannot be loaded

    是mysql账户密码加密规则问题,修改账户加密规则

     #修改加密规则 
    ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
    #更新一下用户的密码 
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
    

    nacos

    version: '3'
    services:
      nacos:
        image: registry.cn-hangzhou.aliyuncs.com/example/nacos:2.0.3
        container_name: nacos  # 容器名为'nacos'
        restart: unless-stopped  # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
        networks:
          docker_net:
            #服务在容器中ip(其他服务引用使用)
            ipv4_address: 172.22.16.100
        volumes:  # 数据卷挂载路径设置,将本机目录映射到容器目录
          - ~/docker/nacos/logs:/home/nacos/logs
          # mysql8版本以上才需要额外此配置信息
          - ~/docker/nacos_mysql_2.0.3/plugins/mysql:/home/nacos/plugins/mysql
        environment:  # 设置环境变量,相当于docker run命令中的-e
          - "PREFER_HOST_MODE=ip"
          - "MODE=standalone"
          - "MYSQL_DATABASE_NUM=1"
          - "SPRING_DATASOURCE_PLATFORM=mysql"
          #容器中mysql服务的ip
          - "MYSQL_SERVICE_HOST= 172.22.16.80"
          - "MYSQL_SERVICE_DB_NAME=nacos"
          - "MYSQL_SERVICE_PORT=3306"
          - "MYSQL_SERVICE_USER=root"
          - "MYSQL_SERVICE_PASSWORD=123456"
        ports:  # 映射端口  (Nacos2.0版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口:9848、9849)
          - "8848:8848"
          - "9848:9848"
          - "9849:9849"
          - "9555:9555"
        mem_limit: 1000m   # 最大使用内存
    networks:
      docker_net:
        external:
          name: docker_net
    

    nginx

    version: '3'
    services:
      nginx:
        image: registry.cn-hangzhou.aliyuncs.com/example/nginx:1.21.1  # 镜像`nginx:1.21.1`
        container_name: nginx  # 容器名为'nginx'
        networks:
          docker_net:
            #服务在容器中ip(其他服务引用使用)
            ipv4_address: 172.22.16.105
        restart: unless-stopped  # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
        volumes:  # 数据卷挂载路径设置,将本机目录映射到容器目录
          - "/home/dubbo/nginx/conf/nginx.conf:/etc/nginx/nginx.conf"
          - "/home/dubbo/nginx/conf/conf.d/:/etc/nginx/conf.d/"
          - "/home/dubbo/nginx/html:/home/dubbo/nginx/html"
          - "/home/dubbo/nginx/log:/var/log/nginx"
        environment:  # 设置环境变量,相当于docker run命令中的-e
          TZ: Asia/Shanghai
          LANG: en_US.UTF-8
        ports:  # 映射端口
          - "80:80"
    networks:
      docker_net:
        external:
          name: docker_net
    

    配置文件信息:nginx.conf

    user  nginx;
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }
    

    配置文件信息:conf.d/default.conf

    server {
            listen       80;
            server_name  localhost;
            client_max_body_size 100M;
            #前端项目1
            location /web/ {
                    root /home/dubbo/nginx/html;
                    index index.html index.htm;
                    try_files $uri $uri/ /index.html; #解决刷新404
            }
            location /api/ {
                    add_header Access-Control-Allow-Origin *;
                    add_header Access-Control-Allow-Methods *;
                    proxy_buffering off;
                    proxy_redirect off;
                    proxy_set_header Host $host:$server_port;
                    proxy_set_header proxy_url "api";
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto  $scheme;
                    proxy_connect_timeout 60;
                    proxy_send_timeout 120;
                    proxy_read_timeout 120;
                    proxy_pass  http://1.15.240.63:6443/api/;
            }
            location /nacos/ {
                    add_header Access-Control-Allow-Origin *;
                    add_header Access-Control-Allow-Methods *;
                    proxy_buffering off;
                    proxy_redirect off;
                    proxy_set_header Host $host:$server_port;
                    proxy_set_header proxy_url "api";
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto  $scheme;
                    proxy_connect_timeout 60;
                    proxy_send_timeout 120;
                    proxy_read_timeout 120;
                    proxy_pass  http://nacos:8848/nacos/;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                    root   html;
            }
    }
    

    前端配置例子:

    volumes:  # 数据卷挂载路径设置,将本机目录映射到容器目录
      - "/home/dubbo/nginx/html:/home/dubbo/nginx/html"
      注意:
      前端项目放在宿主机/home/dubbo/nginx/html下的html目录下,
      nginx启动时会加载更新到docker容器中的/home/dubbo/nginx/html中,可以放多个项目。
    #nginx中前端项目1示例
    location /web/ {
            root /home/dubbo/nginx/html;
            index index.html index.htm;
            try_files $uri $uri/ /index.html; #解决刷新404
    }
    

    前端打包:vue.config.js中module.exports = { 下

    publicPath: '/web/',

    outputDir: 'web',

    assetsDir: 'static',

    productionSourceMap: false,

    前端打包:vue.config.js中publicPath配置 './'时使用第1种:
    nginx使用 第1种: assetsPublicPath: './'
    location / {
        root /home/dubbo/nginx/html;
        index index.html index.htm;
    }
    前端打包:vue.config.js中publicPath配置 '/web/'时使用第2种或者第3种:
    nginx使用 第2种: assetsPublicPath: '/web/'
    location /web/ {
         root /home/dubbo/nginx/html;
         index index.html index.htm;
         try_files $uri $uri/ /index.html; #解决刷新404
    }
    第3种:
    location /web/ {
         alias /home/dubbo/nginx/html/web;
         index index.html index.php index.htm;
    }
    

    redis

    version: '3'
    services:
      redis:
        image: registry.cn-hangzhou.aliyuncs.com/example/redis:6.0.8  # 镜像'redis:6.0.8'
        container_name: redis  # 容器名为'redis'
        networks:
          docker_net:
            #服务在容器中ip(其他服务引用使用)
            ipv4_address: 172.22.16.79
        restart: unless-stopped  # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
        command: redis-server /etc/redis/redis.conf --requirepass 123456 --appendonly no # 启动redis服务并添加密码为:123456,默认不开启redis-aof方式持久化配置
    #    command: redis-server --requirepass 123456 --appendonly yes # 启动redis服务并添加密码为:123456,并开启redis持久化配置
        environment:                        # 设置环境变量,相当于docker run命令中的-e
          TZ: Asia/Shanghai
          LANG: en_US.UTF-8
        volumes:                            # 数据卷挂载路径设置,将本机目录映射到容器目录
          - "./redis/data:/data"
          - "./redis/config/redis.conf:/etc/redis/redis.conf"  # `redis.conf`文件内容`http://download.redis.io/redis-stable/redis.conf`
        ports:                              # 映射端口
          - "6379:6379"
    networks:
      docker_net:
        external:
          name: docker_net
    

    五、使用docker-compose部署服务项目

    gateway-server

    docker-compose -f docker-compose-gateway.yml -p oms-gateway up -d

    version: "3"
    services:
      oms-gateway:
        # 指定容器名称
        container_name: oms-gateway
        networks:
          docker_net:
            #服务在容器中ip(其他服务引用使用)
            ipv4_address: 172.22.16.150
        # 重启机制
        restart: always
        image: java:8
        volumes:
          # 本地jar包路径
          - /home/dubbo/gateway/oms-gateway-1.0.0.jar:/oms-gateway-1.0.0.jar
          # 挂载日志 -v A:B ,A指宿主机位置,B指容器位置
          - /usr/logs:/logs
          # 指定容器时间为宿主机时间
          - /etc/localtime:/etc/localtime
        # 访问端口
        ports:
          - "6443:6443"
        environment:
          TZ: Asia/Shanghai
          LANG: en_US.UTF-8
        #启动容器后执行的命令
        entrypoint: java -server -Xms256m -Xmx256m -jar -Dfile.encoding=utf-8 -Dspring.profiles.active=dev oms-gateway-1.0.0.jar
    networks:
      docker_net:
        external:
          name: docker_net
    

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论