docker入门-Docker Compose

1. docker compose介绍

1.1 什么是docker compose

  • 在部署容器的时候会经过许多步骤,比如创建容器、配置网络、启动容器等等,此时可以把这些命令写成一个脚本。
  • 为了实现这个需求,就创建了docker compose用于简化这些步骤。这个工具通过yml格式的文件去定义需要的操作信息,并且使用docker compose执行该文件:

docker入门-Docker Compose_第1张图片

1.2 docker compose的安装

  • Windows和Mac主机安装了docker desktop之后,docker compose也会自动安装
  • Linux主机可以使用以下命令安装:
$ 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 # 查看是否安装成功
  • 使用pip install docker-composedocker compose是使用python语言写的工具,所以可以使用pip安装)

1.3 compose文件的结构和版本

  • 基本语法结构
version: "3.8"  # 表示docker compose语法的版本

services: # 容器
  servicename: # 服务(容器)名字,这个名字也是内部bridge网络可以使用的DNS name(即可以被其他使用相同bridge网络的容                  器通过该名字ping通)
    image: # 镜像的名字
    command: # 可选,如果设置,则会覆盖默认镜像里的 CMD命令
    environment: # 可选,相当于 docker run里的 --env
    volumes: # 可选,相当于docker run里的 -v
    networks: # 可选,相当于 docker run里的 --network
    ports: # 可选,相当于 docker run里的 -p
  servicename2:

volumes: # 可选,相当于 docker volume create,会被上面的service使用到

networks: # 可选,相当于 docker network create,会被上面的service使用到
  • 以pytnon+Flask+redis练习使用的命令为例,将其改造为docker compose文件:

    练习中的命令如下:

docker image pull redis
docker image build -t flask-demo .

# create network
docker network create -d bridge demo-network

# create container
docker container run -d --name redis-server --network demo-network redis
docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 8080:5000 flask-demo

docker-compose.yml文件内容如下:

version: "3.8"

services:
  flask-demo:
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
    networks:
      - demo-network
    ports:
      - 8080:5000

  redis-server:
    image: redis:latest
    networks:
      - demo-network

networks:
  demo-network:  # 这里没有写别的参数就使用默认的bridge

tips:

  • docker engine的版本为较新版本时也是可以使用老版本的docker compose版本

1.4 docker compose命令行的基本使用

假设已经按照pytnon+Flask+redis练习创建了相应的镜像:

  • 使用docker-compose up去启动docker-compose.yml定义的容器以及网络等,加上-d参数可以让容器在后台运行:

docker入门-Docker Compose_第2张图片

  • 使用docker-compose ps可以查看当前后台运行的容器情况:

docker入门-Docker Compose_第3张图片

  • 使用dockcer-compose stop停止容器
  • 使用docker-compose rm后会删除退出状态的容器,但是创建的网络并不会删除

tips:

  • 在使用docker-compose命令时需要在docker-compose.yml所在目录运行
  • 在查看容器运行情况时,会看到Name中出现root_flaks-demo_1,前缀默认为当前文件夹。前缀名可以使用docker-compose -p xxx up在启动时指定前缀名,但是在后续使用别的命令时都需要加上-p xxx。如果在docker-compose.yml文件中对具体容器使用container_name指定名称后,root_flaks-demo_1就会变为指定名称

2. docker compose镜像构建和拉取

假设当前没有构建flask-demo这个镜像,此时去执行docker-compose up会报错:

在这里插入图片描述

修改后的docker-compose.yml

version: "3.8"

services:
  flask-demo:
    build: 
      context: ./  # 需要指定构建使用的dockerfile所在目录
      dockerfile: Dockerfile_train  # 指定使用的dockrfile
    image: flask-demo:2.0  # 指定构建镜像的名称,不写的话镜像名称默认为root_flaks-demo这样的名称
    environment:
      - REDIS_HOST=redis-server
    networks:
      - demo-network
    ports:
      - 8080:5000

  redis-server:
    image: redis:latest
    networks:
      - demo-network

networks:
  demo-network:  # 这里没有写别的参数就使用默认的bridge

在使用docker-compose up时,假设docker image中没有是需要的镜像,会自动去拉取该镜像。同样也可以使用docker-compose pull/build先去拉取/构建所需镜像,这样可以加快执行docker-compose up的速度

3. docker compose服务更新

假如dockerfile文件中做了修改,此时需要去重新构建镜像:

  • docker-compose build:重新构建docker-compose.yml需要的镜像

  • docker-compose up -d --build:构建作了变更的镜像然后启动服务

4. docker compose网络

  • docker-compose.yml:
version: "3.8"

services:
  box1:
    image: xiaopeng163/net-box:latest  # 多种网络工具的镜像
    command: /bin/sh -c "while true; do sleep 3600; done"
  box2:
    image: xiaopeng163/net-box:latest
    command: /bin/sh -c "while true; do sleep 3600; done"
  • 使用docker-compose up -d创建服务,再使用docker container exec -it root_box1_1 sh进入容器内部(两个容器的名字为root_box1_1和root_box2_1,服务的名字为box1和box2)去ping root_box2_1是可以ping通的,同时ping box2也是可以ping通的
  • 在容器内部使用查询dig root_box2_1(dig是在镜像中安装好的)DNS服务器IP地址为127.0.0.11:53,这个DNS服务器是后台docker engine维护的:

docker入门-Docker Compose_第4张图片

  • 在宿主中使用ping 127.0.0.11是可以ping通的,但是ping root_box1_1是无法ping通的使用。使用more /etc/resolv.conf 可以查看到宿主机的DNS服务器IP地址并不是127.0.0.11
  • 在容器的shell中ping宿主机或百度等是可以ping通的,因为在127.0.0.11这个DNS服务器中找不到域名后,会使用宿主机的DNS服务器

5. docker compose水平扩展和负载均衡

水平扩展即快速增加docker-compose.yml中services的数量

  • docker-compose.yml:
version: "3.8"

services:
  flask:
    build:
      context: ./
      dockerfile: Dockerfile_train
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server

  redis-server:
    image: redis:latest

  client:
    image: xiaopeng163/net-box:latest
    command: sh -c "while true; do sleep 3600; done;"
  • 使用docker-compose up -d --scale flask=3可以将flask的容器增加到3个,同时也可以令flask=1将3个容器减少到1个:

docker入门-Docker Compose_第5张图片

  • 使用docker container exec -it root_client_1 sh进入容器,然后去ping flask(flask是在yml文件中定义的service名称),会发现每次ping通的flask容器IP地址是不一样的:

docker入门-Docker Compose_第6张图片

上面情况就是docker compose实现的负载均衡,使得每次请求可以转发给扩展后不同的容器服务

6. docker compose环境变量

  • docker-compose.yml:
services:
  flask:
    build:
      context: ./flask
      dockerfile: Dockerfile_train
    image: flask:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASSWORD}
    networks:
      - backend
      - frontend

  redis-server:
    image: redis:latest
    command: redis-server --requirepass ${REDIS_PASSWORD}
    networks:
      - backend

在文件中可以看到environment设置了多个环境变量,因为这里变量是密码,将这个yml文件提供给他人时肯定不能直接写入,所以需要将这个环境变量设置为从外部读取的环境变量:

  • 在docker-compose.yml同一个目录下创建.env文件,其中写入REDIS_PASSWORD=123456,在进行代码提交的时候会将该文件加入到.gitignore中。再次进行docker-compose up -d时会自动读取该文件,使用docker-compose config可以查看yml文件中被替换的环境变量:

docker入门-Docker Compose_第7张图片

  • 如果不想设置该文件名为.env,则需要使用docker-compose --env-file .\自定义的文件名 up -d以及docker-compose --env-file .\自定义的文件名 config才能使得配置文件生效

7. 服务依赖和健康检查

7.1 服务依赖

docker-compose.yml文件中可以定义多个service,它们之间可能存在依赖关系,所以它们的启动顺序也是很重要的。实现服务依赖主要是通过depends_on实现:

  • docker-compose.yml:
services:
  flask:
    build:
      context: ./flask
      dockerfile: Dockerfile_train
    image: flask:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASSWORD}
    depends_on:
      - redis-server
    networks:
      - backend
      - frontend

上面表示flak依赖于redis-server,需要先启动redis才能启动flask

7.2 健康检查

有些服务已经启动了,但是无法对外正常提供服务,所以需要检查服务是否正常。在Dockerfiledocker-compose.yml都是可以定义健康检查的命令的:

7.2.1 在Dockerfile中定义健康检查

  • flask的Dockerfile中增加HEALTHCHECK命令,这里表示定期30s检查5000端口是否正常启动,失败的话就exit 1
RUN pip install flask redis && \
    apt-get update && \
    apt-get install -y curl && \
    groupadd -r flask && useradd -r -g flask flask && \
    mkdir /src && \
    chown -R flask:flask /src

USER flask

COPY app.py /src/app.py

WORKDIR /src

ENV FLASK_APP=app.py REDIS_HOST=redis

EXPOSE 5000

HEALTHCHECK --interval=30s --timeout=3s \
    CMD curl -f http://localhost:5000/ || exit 1
CMD ["flask", "run", "-h", "0.0.0.0"]
  • 重新构建flask的镜像并且启动一个容器,此时会发现STATUS中出现unhealthy,因为app.py需要使用到redis,而redis服务还未启动:

docker入门-Docker Compose_第8张图片

  • 启动redis容器后,STATUS变为healthy,同样可以是docker inspect去查看记录健康检查的日志:

docker入门-Docker Compose_第9张图片

docker入门-Docker Compose_第10张图片

7.2.2 在docker-compose.yml中定义健康检查

  • 对flask进行健康检查,将docker-compose.yml文件修改如下(上节在flask的Dockerfile文件中添加的代码可以删除):
version: "3.8"

services:
  flask:
    build:
      context: ./flask
      dockerfile: Dockerfile_train
    image: flask:latest
    environment:
      - REDIS_HOST=redis-server
      - REDIS_PASS=${REDIS_PASSWORD}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s
    depends_on:
      - redis-server
    networks:
      - backend
      - frontend
  • 使用docker-compose up -d创建服务,再使用docker-compose ps查看信息时会显示健康状态(这里将docker-compose.yml文件中redis密码修改同.env文件不一致所以显示unhealthy):

docker入门-Docker Compose_第11张图片

  • 此时发现依赖于flask的nginx还是启动了,要对nginx进行健康检查需要修改docker-compose.yml中nginx部分为:
  nginx:
    image: nginx:stable-alpine
    ports:
      - 8000:80
    depends_on:
      flask:
        condition: service_healthy
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./var/log/nginx:/var/log/nginx
    networks:
      - frontend
  • 再次使用docker-compose up -d创建服务,会显示无法创建nginx服务:

docker入门-Docker Compose_第12张图片

8. 参考

  1. https://dockertips.readthedocs.io/en/latest/docker-compose.html

  2. https://docs.docker.com/compose/compose-file/

  3. https://github.com/dockersamples/example-voting-app

你可能感兴趣的:(docker,docker,linux,运维,docker-compose)