Docker Compose 容器编排

04-27 7890阅读 0评论

什么是 Docker Compose

docker-compose 是 Docker 官方的开源项目,使用 python 编写,实现上调用了 Docker 服务的 API 进行容器管理及编排,其官方定义为定义和运行多个 Docker 容器的应用。


docker-compose 中有两个非常重要的概念:

  • 服务 ( service ): 一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目( project ): 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义,整个 docker-compose.yml 定义一个项目。

    Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。通过 compose 可以方便的管理多个服务。

    为什么要 Docker Compose

    Docker 是一个轻量化的应用程序,Docker 官方推荐每个 Docker 容器中只运行一个进程。

    • 如果一个应用需要涉及到 MySQL、nginx 等环境, 那么我们需要分别为应用、数据库和 nginx 创建单独的 docker 容器,然后分别启动容器。
    • 想象一下,当我们构建好 Docker 之后,每次启动应用,都至少需要 docker run 三次, 或者写一些脚本来实现, 这样会比较繁琐。
    • 另外,这些 docker 容器都是分散独立的,也不方便镜像管理。那既然这些 docker 容器 都是为了同一个应用服务,我们就应该把它们放到一起,这就引出了 docker-compose 来解决这类型的问题。

      Docker Compose 的功能

      1. Docker Compose 使用步骤
        • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
        • 最后,执行 docker compose up 命令来启动并运行整个应用程序。
        • 核心功能:Compose 具有管理应用程序整个生命周期的命令:
          • 启动,停止和重建服务
          • 查看正在运行的服务的状态
          • 流式传输运行服务的日志输出
          • 在服务上运行一次性命令

      Docker Compose 使用场景

      • 单主机部署:快速搭建一个单节点开发或者测试环境,方便使用。
      • 不同环境隔离:通过指定 project 来运行不同的环境,实现隔离的目的。

        Docker Compose 常见指令

        我们讲解的 Docker Compose 版本是 3.8 的版本哈!这里只会提到部分 Docker Compose 的指令!如果你需要查看全部的指令,可以访问这个网址:Docker Compose Version3

        关于首行写不写 version 字段,参考,在我的 Docker Compose 版本中写上这个 version 字段会报警告!

        Docker Compose 容器编排 第1张

        version: "3.8" # 指定使用那个语法版本的 Compose File
        services: # 这个 services 就和上面的服务对应 可以有多个 services
          yourproject: # 这个就和上面的服务对应,名字根据需求来取哈!
        

        上面是 Docker Compose File 的固定格式吧,我们要学习的指令是在一个具体的服务中生效的!

        image

        • 指定要从哪个镜像启动容器。格式有如下几种,任选一种即可!
          image: redis
          image: redis:5
          image: redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7
          image: library/redis
          image: docker.io/library/redis
          image: my_private.registry:5000/redis
          
          • 演示:
            version: "3.8"
            services:
              mynginx:
                image: nginx
            
            • 如果我们的本地没有你在 docker-compose.yml 指定的镜像,他会自动拉取的哈!!
            • docker compose up 命令会自动解析当前目录下的 docker-compose.yml 文件,-d 表示后台运行。
            • 可以看到,启动容器的名字和我们指定服务的名称还是有关系的哈!mynginx 与 compose-mynginx-1 有关系不是吗?其中 compose 是 docker-compose.yml 所在的目录名!

              Docker Compose 容器编排 第2张

              command

              覆盖容器启动的默认命令。

              两种格式哈:

              command: bundle exec thin -p 3000
              
              command: ["bundle", "exec", "thin", "-p", "3000"]
              
              • 演示:

                可以看到,我的本地有个 busybox 的镜像,我们查看镜像的详细内容,可以看到他的默认启动命令是 sh

                Docker Compose 容器编排 第3张

                下面我们编写 docker-compose.yml 文件修改这个镜像的默认启动命令。

                services:
                  mybusybox:
                    image: busybox
                    command: ["sh", "-c", "while true; do echo 'hello docker!'; sleep 1; done"]
                    stdin_open: true # 配置容器的标准输入
                    tty: true # 配置容器的终端,不然无法 -d 后台运行
                
                • docker compose config 可以检查你的 docker-compose.yml 文件是否有语法错误哈!
                • 通过 docker ps 命令可以看到容器的 COMMAND 已经被覆盖了哈!

                  Docker Compose 容器编排 第4张

                  environment

                  添加环境变量。可以使用数组或字典,任何布尔值 (布尔值需要引号引起来)。

                  有下面两种格式,看你喜欢哪种吧!

                  # map 语法
                  environment:
                    RACK_ENV: development
                    SHOW: "true"
                    USER_INPUT:
                  #数组语法
                  environment:
                    - RACK_ENV=development
                    - SHOW=true
                    - USER_INPUT
                  
                  • 演示:
                    services:
                      mybusybox:
                        image: busybox
                        command: ["sh", "-c", "while true; do echo 'hello docker!'; sleep 1; done"]
                        stdin_open: true
                        tty: true
                        environment:
                          MY_ENV: TCHEY
                    

                    可以看到,通过 environment 命令,我们成功给启动的容器设置了 MY_ENV 这个环境变量哈!

                    Docker Compose 容器编排 第5张

                    networks

                    指定容器运行时的网络!

                    • 演示:
                      services:
                        mynginx:
                          image: nginx
                          networks:
                            - mynetwork1
                            - mynetwork2
                      networks:
                        mynetwork1:
                        mynetwork2:
                      

                      在上面的 docker-compose.yml 文件中,我们定义了两个网络。我们指定镜像为 nginx 并且给容器配置了这两个网络。

                      如下图:我们启动一个容器,可以看到会自动创建我们之前定义的网络!

                      Docker Compose 容器编排 第6张

                      我们输入 docker inspect 命令查看容器的详情:可以看到容器包含的两个网络符合预期,并且一些必要的信息由 Docker 帮我们自动分配了!因为我们没有在 docker-compose.yml 文件中指定嘛!

                      Docker Compose 容器编排 第7张

                      volumes

                      将主机的文件挂载到容器里。

                      #短语法
                      services:
                       db:
                        image: postgres:latest
                        volumes:
                          - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
                          - "/localhost/data:/var/lib/postgresql/data"
                       
                      #完整语法
                      services:
                        backend:
                        image: awesome/backend
                        volumes:
                          - type: volume
                            #命名卷
                            source: db-data
                            target: /data
                            volume:
                            nocopy: true
                            #绑定卷
                          - type: bind
                            source: /var/run/postgres/postgres.sock
                            target: /var/run/postgres/postgres.sock
                      volumes:
                         db-data:
                      
                      • 演示:
                        services:
                          mynginx:
                            image: nginx
                            networks:
                              - mynetwork1
                              - mynetwork2
                            volumes:
                              - /root/html:/usr/share/nginx/html
                        networks:
                          mynetwork1:
                          mynetwork2:
                        

                        在上面的 docker-compose.yml 文件中,我们使用 volumes 命令建立了宿主机与容器的目录映射关系。

                        如下图:可以看到宿主机中并不存在 /root/html 这样的目录!

                        当我们使用 docker compose up 命令启动一个容器之后,目录就会自动创建了!

                        Docker Compose 容器编排 第8张

                        因为我们没有开放端口,所以只能在本机访问 nginx 服务器,curl 127.0.0.1 之后得到的是 403 forbidden 因为我们创建的是绑定卷,宿主机中原本不存在我们指定的映射目录,容器中的目录就会被清空!所以看到的是 403 forbidden

                        Docker Compose 容器编排 第9张

                        我们再启动一个 shell 修改宿主机 /root/html 目录下的内容之和,再次 curl 127.0.0.1 可以看到内容发生了变化!

                        Docker Compose 容器编排 第10张

                        ports

                        指定端口映射。

                        有多种格式,看你喜欢哪一种咯!

                        #完整语法
                        ports:
                          - target: 80
                             host_ip: 127.0.0.1
                             published: 8080
                             protocol: tcp
                             mode: host
                           - target: 80
                             host_ip: 127.0.0.1
                             published: 8000-9000
                             protocol: tcp
                             mode: host
                        #短语法
                        ports:
                          - "3000"
                          - "3000-3005"
                          - "8000:8000"
                          - "9090-9091:8080-8081"
                          - "49100:22"
                          - "127.0.0.1:8001:8001"
                          - "127.0.0.1:5000-5010:5000-5010"
                          - "6060:6060/udp" 
                        
                        • 演示:
                          services:
                            mynginx:
                              image: nginx
                              networks:
                                - mynetwork1
                                - mynetwork2
                              volumes:
                                - /root/html:/usr/share/nginx/html
                              ports:
                                - 9999:80/tcp
                          networks:
                            mynetwork1:
                            mynetwork2:
                          

                          在上面的 docker-compose.yml 文件中我们以短语法的形式指定了宿主机与容器的端口映射!

                          使用 docker compose config 命令查看,可以看到短语法最终还是会被 Docker 的 yml 解释器解释为长语法!

                          Docker Compose 容器编排 第11张

                          使用 IP 地址加上端口号访问,成功访问到 nginx 的主页!

                          因为我们之前添加了绑定卷,并且对 index.html 文件做了修改,所以看到的是这个哇!

                          Docker Compose 容器编排 第12张

                          expose

                          暴露端口,但不映射到宿主机,只被连接的服务访问。可以理解为一种声明吧!

                          expose:
                            - "3000"
                            - "8000"
                          

                          depends_on

                          设置依赖关系。

                          • docker compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和redis ,才会启动 web。
                          • docker compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker compose up web 还将创建并启动 db 和 redis。
                          • docker compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
                            services:
                              web:
                                depends_on:
                                  - db
                                  - redis
                              redis:
                                image: redis
                              db:
                                image: postgres
                            

                            我们也可以指定一个服务的状态作为另一个服务的启动的条件!例如:只有当 MySQL 的启动是健康的,再启动 nginx 服务。

                            要实现这个,我们可以使用 helthcheck 命令来实现。

                            • 演示:
                              services:
                                mynginx:
                                  image: nginx
                                  ports:
                                    - 9999:80/tcp
                                  depends_on: # mynginx 服务依赖于 mysql 的健康启动
                                    mysql:
                                      condition: service_healthy
                                mysql:
                                  image: mysql:5.7
                                  environment:
                                    MYSQL_ROOT_PASSWORD: "root" # mysql 的启动必须加上这个环境变量,详情参见 dockerhub 官网
                                  healthcheck:
                                    test: mysql --user=root --password='root' -e "SELECT 1;" # -e 指定执行的 sql 语句
                                    interval: 10s # 每次尝试的间隔
                                    timeout: 5s   # 每次尝试的超时时间
                                    retries: 10   # 尝试多少次
                              

                              在上面的 docker-compose.yml 文件中,我们让 mynginx 服务的启动依赖于 mysql 服务的健康启动!我们给 mysql 服务设置了 healthcheck 检查的条件就是能够正确执行一个 sql 语句。

                              我们使用 docker compose up 启动容器,可以看到 mysql 服务只有启动起来,并且处于 Healthy 状态,mynginx 服务才会启动哈!mynginx 服务启动得太快了,我没有截图到!

                              如果 mysql 服务没能以 Healthy 状态启动,容器只是创建出来了,没法启动的!

                              Docker Compose 容器编排 第13张

                              我们使用 docker compose stop 命令停止整个项目,可以看到先停止的也是 mysql 服务哈!

                              Docker Compose 容器编排 第14张

                              • 补充:

                                我们在 mysql 服务中加上两个绑定卷:

                                • 将宿主机的 /root/varnt/lib/ 目录与容器的 /var/lib/mysql 目录绑定!这是mysql 存放数据的目录,建立这个映射能防止容器挂掉而导致数据丢失
                                • 将宿主机的 /root/entry_point/ 目录与容器的 /docker-entrypoint-initdb.d 目录绑定!mysql 启动的时候,会扫描/docker-entrypoint-initdb.d 目录下以.sql .sh 结尾的文件并执行

                                  Docker Compose 容器编排 第15张

                                  我们在宿主机手动创建 /root/entry_point/ 这个目录,并在这个目录下创建一个文件 init.sql。在里面写上几个 sql 语句:

                                  -- 创建 student 数据库
                                  CREATE DATABASE IF NOT EXISTS student;
                                  -- 切换到 student 数据库
                                  USE student;
                                  -- 创建 score 表
                                  CREATE TABLE IF NOT EXISTS score (
                                      id INT PRIMARY KEY AUTO_INCREMENT,
                                      chinese FLOAT,
                                      english FLOAT,
                                      math FLOAT
                                  );
                                  -- 插入一条数据
                                  INSERT INTO score (chinese, english, math) VALUES (85.5, 90.0, 78.5);
                                  

                                  我们使用 docker compose up 命令启动容器,可以看到在宿主机能够看到数据库中的数据!

                                  Docker Compose 容器编排 第16张

                                  我们进入 mysql 看看数据库,表,是否创建成功,数据是否插入成功!即看看 init.sql 文件中的 sql 语句是否在 mysql 启动的时候被执行了!

                                  可以看到 student 数据库创建成功:

                                  Docker Compose 容器编排 第17张

                                  可以看到,表创建成功,数据插入成功!!!

                                  Docker Compose 容器编排 第18张

                                  env_file

                                  从文件添加环境变量。可以是单个值或列表的多个值。

                                  # 可以是这种格式
                                  env_file: .env
                                  # 也可以是列表格式:
                                  env_file:
                                   - ./common.env
                                   - ./apps/web.env
                                   - /opt/secrets.env
                                  
                                  • 演示:
                                    services:
                                      mynginx:
                                        image: nginx
                                        env_file:
                                          - ./env.ini
                                    

                                    在上面的 docker-compose.yml 文件中,我们指定 env_file 为当前目录的 env.ini。我们在当前目录下创建 env.ini 随便写几个环境变量!

                                    MY_ENV1=1
                                    MY_ENV2=2
                                    MY_ENV3=3
                                    MY_ENV4=4
                                    MY_ENV5=5
                                    

                                    我们使用 docker compose up -d 启动我们的容器!

                                    Docker Compose 容器编排 第19张

                                    进入容器,我们打印环境变量,观察是否成功设置:

                                    Docker Compose 容器编排 第20张

                                    docker-compose.yml 文件中的命令多得很,这里实在是没法讲完!大家可以去 docker hub 官网查看!

                                    链接上面已经贴过啦!是不是以为我不会贴了!那你就错了!DockerComposeFile Reference

                                    Docker Compose 命令清单

                                    命令描述
                                    docker compose build构建服务
                                    docker compose config规范的格式来显示服务配置
                                    docker compose cp在本地系统和服务容器直接拷贝文件
                                    docker compose create创建服务的容器
                                    docker compose down停止所有容器,并删除容器
                                    docker compose events从服务器获取实时事件
                                    docker compose exec在容器中执行命令
                                    docker compose images列出所有容器使用的镜像
                                    docker compose kill强制停止服务的容器
                                    docker compose logs显示日志
                                    docker compose ls显示所有项目
                                    docker compose pause暂停服务
                                    docker compose port列出所有的端口映射
                                    docker compose ps该命令可以列出项目中目前的所有 容器
                                    docker compose pull拉取服务镜像
                                    docker compose push推送服务镜像
                                    docker compose restart重启或者重启某个服务
                                    docker compose rm删除服务停止的容器
                                    docker compose run在指定服务容器上执行相关的命令
                                    docker compose start启动当前停止的某个容器
                                    docker compose stop停止当前运行的某个容器
                                    docker compose top显示运行的进程
                                    docker compose unpause恢复服务
                                    docker compose upup 命令会构建,(重新)创建,启 动,链接一个服务相关的容器。默 认情况下如果容器已经存在,将会 停止并尝试重新创建他们。并使用 之前挂载的卷。–no-recreate 参数 可以让容器不被停止或者重新创 建,-d 表示后台运行
                                    docker compose version查看版本

                                    好多啊!别记,用到了到时候查就行了!

                                    命令格式

                                    对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响。

                                    • docker-compose 命令的基本的使用格式为
                                      docker compose [OPTIONS] COMMAND [ARGS...]
                                      

                                      常见选项说明

                                      • -f, --file 指定使用的 Compose 模板文件,默认为 docker-compose.yml。
                                      • -p, --project-name 指定项目名称,默认将使用所在目录名称作为项目名。

                                        docker compose up

                                        该命令的作用十分强大,它会尝试自动完成包括构建镜像、(重新)创建服务、启动服务并关联服务相关容器的一系列操作,可以直接通过该命令来启动一个项目。

                                        docker compose up [options] [SERVICE...]
                                        
                                        • -d :在后台运行服务容器, 推荐在生产环境下使用该选项。
                                        • --force-recreate :强制重新创建容器,不能与 --no-recreate 同时使用。
                                        • --no-recreate :如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。

                                          docker compose down

                                          停止所有容器,并删除容器和网络

                                          docker compose down [options] [SERVICE...]
                                          
                                          • -v, --volumes: 删除容器同时删除目录映射

                                            docker compose run

                                            该命令可以在指定服务容器上执行相关的命令。

                                            例如:启动一个 ubuntu 服务容器,并执行 ping docker.com 命令

                                            docker compose run ubuntu ping docker.com

                                            docker compose run [options] SERVICE [COMMAND] [ARGS...]

                                            • -d:后台运行容器
                                            • --name NAME: 为容器指定一个名字。
                                            • --entrypoint CMD: 覆盖默认的容器启动指令。
                                            • -e KEY=VAL: 设置环境变量值,可多次使用选项来设置多个环境变量。
                                            • -u, --user="" :指定运行容器的用户名或者 uid。
                                            • --rm: 运行命令后自动删除容器。
                                            • -p, --publish=[]: 映射容器端口到本地主机。

                                              常见问题

                                              1. up、run 和 start 之间有什么区别

                                                通常,你想要 docker compose up。用于 up 启动或重新启动 docker-compose.yml 在默认的“附加”模式下,会看到来自所有容器的所有日志。在“分离”模式 ( -d) 中,启动容器后 Compose 退出,但容器继续在后台运行。该 docker compose run 命令用于运行“一次性”或“临时”任务。它需要您要运行的服务名称,并且只为正在运行的服务所依赖的服务启动容器。用于 run 运行测试或执行管理任务,例如从数据卷容器中删除或添加数据。该 run 命令的作用类似于 docker run -ti 它打开容器的交互式终端并返回与容器中进程的退出状态匹配的退出状态。docker compose start 命令仅对重新启动先前创建但已停止的容器有用。它从不创建新容器。

                                              2. 如何在同一主机上运行 Compose 文件的多个副本

                                                Compose 使用项目名称为项目的所有容器和其他资源创建唯一标识符。要运行项目的多个副本,请使用-p 命令行选项 或 COMPOSE_PROJECT_NAME 环境变量设置自定义项目名称。

                                              3. 可以控制服务启动顺序吗?

                                                可以控制启动顺序,通过依赖指定,并且可以配合 healthcheck 等健康检查成功以后再启动。


免责声明
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明。
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所
提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何
损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在
转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并白负版权等法律责任。

手机扫描二维码访问

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,7890人围观)

还没有评论,来说两句吧...

目录[+]