docker使用经验总结(三、Docker compose基础应用)

六、Docker compose:Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Docker Compose,用户可以使用一个 YAML 文件来定义应用程序所需的所有服务,然后通过一条命令就可以创建并启动这些服务。Docker Compose 可以极大简化多容器应用的管理和部署流程。

它的原理,Docker Compose 主要依赖于两个核心部分:

  • YAML 文件 (docker-compose.yml):这个文件用来描述多容器应用的各个服务以及它们之间的关系。通过定义各个服务的镜像、网络、卷、端口映射等,Compose 可以在本地环境或生产环境中一致性地部署应用。

  • Docker Compose CLI:Docker 提供了一个命令行工具 docker-compose,用户可以通过它来管理使用 docker-compose.yml 定义的服务。这些命令包括启动、停止、重启服务,查看日志等。

 1. compose.yml:是 Docker Compose 用来定义多容器应用的核心配置文件。它使用 YAML 语法描述服务、网络、卷和其他配置项。下面是一个典型的 docker-compose.yml 文件结构及其各部分的详细说明。

YAML 文件不必须命名为 docker-compose.yml,但默认情况下,Docker Compose 会在当前目录下查找名为 docker-compose.yml 的文件作为配置文件。如果想使用其他名称的 YAML 文件,也完全可以,只需要在运行 Docker Compose 命令时显式指定该文件的路径和名称。

version: '3.8'  # 指定 Docker Compose 文件的版本

services:  # 定义服务
  web:  # 服务名称,可以是任意名称
    image: nginx:alpine  # 使用的镜像
    ports:
      - "8080:80"  # 端口映射:将主机的8080端口映射到容器的80端口
    volumes:
      - ./html:/usr/share/nginx/html  # 挂载本地目录到容器中的路径
    networks:
      - webnet  # 指定服务使用的网络
    depends_on:
      - app  # 指定依赖的服务,确保app服务在web服务之前启动

  app:  # 另一个服务
    build: ./app  # 使用本地的Dockerfile构建镜像
    command: python app.py  # 覆盖默认命令
    volumes:
      - ./app:/app  # 挂载本地目录到容器中
    environment:
      - DEBUG=1  # 设置环境变量
    networks:
      - webnet  # 指定服务使用的网络

volumes:  # 定义数据卷
  db_data:  # 卷名称,可以在 services 中引用
    driver: local  # 指定驱动类型,这里是本地驱动

networks:  # 定义网络
  webnet:  # 网络名称
    driver: bridge  # 指定网络驱动类型

version

version 定义了 docker-compose.yml 文件的版本,版本决定了可以使用的语法和功能。常见版本包括 '3.8''3''2' 等。一般建议使用较新的版本以确保兼容最新功能。

services

services 是最核心的部分,定义了应用中所有的服务。每个服务包含以下常用配置项:

  • image: 指定要使用的 Docker 镜像。如果该镜像不存在,Compose 会自动从 Docker Hub 拉取。
  • build: 如果你希望构建自己的镜像,可以使用 build 选项,通常指定一个包含 Dockerfile 的路径。
  • ports: 端口映射,HOST:CONTAINER 格式,将主机的端口映射到容器内的端口。
  • volumes: 卷挂载,HOST_PATH:CONTAINER_PATH 格式,将主机的目录或文件挂载到容器内。
  • networks: 指定服务使用的网络。可以在下面的 networks 部分定义这些网络。
  • environment: 设置环境变量,可以在容器内访问这些变量。
  • depends_on: 指定服务之间的依赖关系,确保某些服务在其他服务启动之前启动。
  • command: 覆盖默认的容器启动命令。
  • restart: 定义容器的重启策略(如 alwayson-failure)。

volumes

volumes 用于定义和管理数据卷。数据卷用于持久化数据,即使容器被删除,数据仍然存在。

  • driver: 定义卷的驱动类型,默认是 local

卷可以在 services 中引用,作为数据存储的路径。

networks

networks 用于定义服务之间的网络配置。

  • driver: 指定网络驱动类型,常见的有 bridgeoverlay 等。

网络可以被多个服务共享,用于服务之间的通信。

 

2.常用基础命令:Docker Compose 的命令大多数是在项目的根目录下执行的,该目录包含 docker-compose.yml 文件。Docker Compose 会自动在当前目录查找 docker-compose.yml 文件,并根据其中定义的内容执行相关操作。

# 启动应用:命令会读取当前目录下的 docker-compose.yml 文件,并启动所有定义的服务。如果服务所需的镜像不存在,Compose 会自动构建或拉取镜像。如果想在后台运行,可以加上 -d 参数
docker compose up -d

# 启动已经存在的容器,而不会重新创建它们。如果容器已经存在但未运行,此命令可以用来重新启动它们。

  docker compose start


# 命令会停止所有正在运行的服务
docker compose stop

# 重启服务,且在不指定服务名称,docker-compose 将重启所有服务
docker compose restart [SERVICE_NAME]

# 列出当前所有服务的状态
docker compose ps

# 看指定服务的日志。如果不指定服务名称,则会查看所有服务的日志
docker compose logs [SERVICE_NAME]

# 运行一次性命令
docker compose run SERVICE_NAME COMMAND

# 在正在运行的容器中执行命令
docker compose exec # 在 docker-compose.yml 中定义了 build 选项,可以用这个命令来构建镜像 docker compose build # 停止并删除所有在 docker-compose.yml 中启动的服务、网络和挂载的卷。如果你想删除服务但保留卷数据,可以加上 --volumes 选项 docker compose down --volumes

其中,docker compose up有几个参数要重点讲下

# --scale SERVICE=NUM:指定服务的容器数量,例如可以扩展 web 服务到 3 个副本。
docker compose up --scale web=3

# 制构建服务镜像,即使镜像已经存在
docker compose up --build

# 删除不在 docker-compose.yml 文件中的多余容器
docker compose up --remove-orphans

 

2. 使用流程

  • 定义应用环境:在 docker-compose.yml 文件中定义应用程序所需的各个服务。
  • 启动应用:使用 docker-compose up 命令启动整个应用,Compose 会根据 docker-compose.yml 文件创建并启动所有服务。
  • 管理服务:使用 docker-compose 提供的其他命令,如 stop, start, restart,scale等来管理已经启动的服务。
  • 删除应用:通过 docker-compose down 命令停止并删除所有服务及其相关资源。

3.实践

假设有一个前后端分离的 Python + Django + MySQL + Redis + Vue + Nginx 项目,我们需要为各个组件编写Dockerfile,并在 docker-compose.yml 文件中配置服务。

目录结构:

myproject/
├── backend/
│   ├── Dockerfile
│   ├── myproject/
│   ├── manage.py
│   ├── requirements.txt
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   ├── src/
│   └── ...
├── nginx/
│   ├── Dockerfile
│   ├── nginx.conf
├── docker-compose.yml

3.1 Backend(Django)部分

backend/Dockerfile:

# 使用官方的 Python 镜像作为基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . /app/

# 暴露应用端口
EXPOSE 8000

# 运行 Django 开发服务器(你可能需要使用 gunicorn 或者其他 WSGI 服务器在生产环境中)
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

backend/requirements.txt,在这个文件中,列出 Django 项目所需的所有 Python 包,如:

Django>=3.2,<4.0
mysqlclient
redis
gunicorn

3.2 Frontend(Vue.js)部分

frontend/Dockerfile:

# 使用 Node.js 镜像作为基础镜像
FROM node:14-alpine

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY package.json yarn.lock /app/
RUN yarn install

# 复制源代码
COPY . /app/

# 构建 Vue.js 应用
RUN yarn build

# 运行 Vue.js 应用(在开发时可能用 npm run serve;在生产环境中通常用 nginx 或 serve 静态资源)
EXPOSE 8080
CMD ["yarn", "serve"]

3.3 Nginx 部分

nginx/Dockerfile:

# 使用官方 Nginx 镜像作为基础镜像
FROM nginx:alpine

# 删除默认的配置文件
RUN rm /etc/nginx/conf.d/default.conf

# 复制自定义的 Nginx 配置文件
COPY nginx.conf /etc/nginx/conf.d/

# 复制前端构建的静态文件到 Nginx 容器
COPY --from=frontend /app/dist /usr/share/nginx/html

# 暴露端口
EXPOSE 80

nginx/nginx.conf: 这是一个 Nginx 配置文件的示例,反向代理到 Django 和 Vue.js 应用

server {
    listen 80;

    # 静态文件处理(Vue.js)
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    # 代理请求到 Django 应用
    location /api/ {
        proxy_pass http://backend:8000/;
        proxy_set_header Host $host;
        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;
    }
}

3.4 Docker Compose 文件

docker-compose.yml:

version: '3.8'

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

  redis:
    image: redis:alpine
    restart: always
    networks:
      - backend

  backend:
    build: ./backend
    command: ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
    volumes:
      - ./backend:/app
    ports:
      - "8000:8000"
    environment:
      - DATABASE_HOST=db
      - DATABASE_PORT=3306
      - DATABASE_NAME=mydatabase
      - DATABASE_USER=myuser
      - DATABASE_PASSWORD=mypassword
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - db
      - redis
    networks:
      - backend

  frontend:
    build: ./frontend
    volumes:
      - ./frontend:/app
    ports:
      - "8080:8080"
    networks:
      - frontend

  nginx:
    build: ./nginx
    ports:
      - "80:80"
    depends_on:
      - frontend
      - backend
    networks:
      - frontend
      - backend

volumes:
  db_data:

networks:
  frontend:
  backend:

启动项目:在 myproject/ 目录下运行命令:docker compose up --build -d. 启动所有服务。通过 http://localhost 访问前端应用,后端 API 在 http://localhost/api/ 路径下。