Docker-compose使用及举例

一、简介

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 之后可以直接使用。运行以下指令检查是否安装成功:

css 复制代码
$ docker-compose --version
​
docker-compose version 1.29.2, build b02f1306

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

软件包方式安装

以ubuntu为例:

ruby 复制代码
$ sudo apt install docker-compose

二进制包

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

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

ruby 复制代码
$ 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 源中安装。

执行安装命令:

ruby 复制代码
$ sudo pip install -U docker-compose

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

卸载

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

shell 复制代码
$ sudo rm /usr/local/bin/docker-compose

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

ruby 复制代码
$ sudo pip uninstall docker-compose

三、创建自定义网络

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

1. 创建自定义网络

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

2. 查看网络

bash 复制代码
docker network ls

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

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

ini 复制代码
# 运行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. 查看容器网络

bash 复制代码
# 还可以进入容器,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

yaml 复制代码
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

yaml 复制代码
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

yaml 复制代码
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从任何主机登录)

sql 复制代码
create user 'root'@'%' identified by  '123456';

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

sql 复制代码
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

3.刷新权限

arduino 复制代码
flush privileges;

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

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

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

nacos

perl 复制代码
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

yaml 复制代码
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

dart 复制代码
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

ini 复制代码
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;
        }
}

前端配置例子:

bash 复制代码
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,

bash 复制代码
前端打包: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

yaml 复制代码
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

yaml 复制代码
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
相关推荐
tangdou3690986551 小时前
Docker系列-超级详细教你Linux安装并使用docker compose,如何使用docker-compose安装sqlserver
docker·容器·sql server
tangdou3690986551 小时前
手把手非常详细图文并茂教你 Docker 部署 SQL Server
docker·容器·sql server
飘逸高铁侠14 小时前
docker export/import 和 docker save/load 的区别
docker·容器·eureka
大宇进阶之路15 小时前
docker运行arm64架构的镜像、不同平台镜像构建
docker·微服务·架构
长天一色18 小时前
【Docker从入门到进阶】04.高效实践
运维·docker·容器
binqian18 小时前
【Docker】 进入容器的几种方式
运维·docker·容器
杨浦老苏1 天前
Markdown笔记管理工具Haptic
笔记·docker·markdown·群晖
长天一色1 天前
【Docker从入门到进阶】03.进阶应用
运维·docker·容器
AlenTech1 天前
Ubuntu 安装 Docker Compose
ubuntu·docker·eureka
吾在水一方1 天前
docker部署禅道使用内置mysql
mysql·docker·容器