Docker进阶

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。

前言:

前面我们讲了dockerfile文件用以构建镜像,然后通过镜像就能运行容器。

但是如果你要开发一个前后端网站你可能会需要Mysql、Redis、Nginx等,那么难道我们要一个一个的使用 docker run来创建容器并运行吗?这个时候我们就需要docker-compose了。

如果说dockerfile是构建单个镜像的脚本。

那么docker-compose就是一个可以用于定义和运行多容器 Docker 应用程序的工具。

Docker Compose 的核心概念

Docker Compose 官方文档

  • 服务(Services): 一个服务代表一个应用程序容器。在 docker-compose.yml 文件中,需要定义每个服务的镜像、端口映射、环境、卷挂载等配置。
  • 网络(Networks): Docker Compose 会自动为你的应用程序创建一个默认网络,以便所有服务都能通过服务名称相互通信。
  • 卷(Volumes): 卷用于持久化数据。你可以将数据库的数据目录挂载到宿主机上,这样即使容器被删除,数据也不会丢失。

使用Docker Compose

docker-compose.yml 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
version: '3.8'

# 定义网络
networks:
  my-network:
    driver: bridge

services:
  # Web 服务器服务
  web:
	image: ghcr.io/munakanisena/zx-picture-frontend:latest #github-docker存储
    ports:
      - 80:80
      - 403:403
    restart: always
  
  #sever 服务器服务
  server:
    build:
    context: ./app  # 指定 Dockerfile 所在的目录
    depends_on:
      - mysql
      - redis
    environment:
      - SPRING_DATASOURCE_URL
      - SPRING_DATASOURCE_USERNAME
      - SPRING_DATASOURCE_PASSWORD
      - SPRING_REDIS_HOST
      - SPRING_REDIS_PASSWORD
    ports:
      - 8123:8123
    restart: always
    
  #Mysql存储服务
  mysql:
    image: mysql:8.0 # 使用官方 Mysql 镜像
    environment:
      - MYSQL_ROOT_PASSWORD
      - MYSQL_DATABASE
    ports:
      - 3306:3306
    volumes:
      - ./data/mysql:/var/lib/mysql
      - ./sql/new_create-table_zx.sql:/docker-entrypoint-initdb.d/init.sql:ro
    restart: always

  # Redis 缓存服务
  redis:
    image: "redis:alpine" # 使用官方 Redis 镜像
    restart: always

参数解析

注:已说明的不会重复说明

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

networks: 定义了一个名为 my-network 的自定义网络,方便容器之间通信。

services: 定义了四个服务,web servermysqlredis

服务名称可以自定义,之后容器通讯可以直接使用服务名

注意:

由于每一个容器都有一个独立的网络环境。所以一般你的容器是访问不了别的容器的。

因此你需要一个容器的互联网来让容器互相交流。

因此如果你要使用前端nginx代理转发时不要写成 localhost:8123,而是应该直接写定义的server服务名。

web服务:

这是一个前端 Web 服务器。

  • image: 直接使用一个位于 GitHub 容器注册表(ghcr.io)的最新镜像,而不是从本地构建。
  • ports: 将容器内的 80 和 403 端口映射到宿主机的 80 和 403 端口,用于外部访问。
  • restart: always: 确保容器在退出时会自动重启。

server 服务

这是一个后端服务器。

  • build: 使用 ./app 目录下的 Dockerfile 文件构建的镜像。
  • depends_on: 声明此服务依赖 mysqlredis (就是你自定义的服务名)服务,确保它们在 server 服务启动前就绪。
  • environment: 定义了一系列环境变量,用于配置数据库和 Redis 的连接信息。这些变量需要在运行容器时进行设置。

mysql 服务

这是一个 MySQL 数据库服务。

  • environment: 定义了数据库的根密码和默认数据库名称。

**redis服务 **

这是一个 Redis 缓存服务。

  • image: 使用轻量级的 redis:alpine 镜像。
  • restart: always: 容器退出时自动重启

这里着重说一下environmentvolumes

environment 环境

工作原理:当 Docker Compose 启动一个服务时,它会读取 environment 字段中定义的键值对,并将它们作为环境变量传递给该服务所运行的容器。

那么这些环境变量在哪里来的?
  • 直接在 docker-compose.yml 中赋值:
1
2
 environment:
   - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/db
  • 从宿主机的环境变量中继承: 如果 SPRING_DATASOURCE_URL 在运行 docker-compose up 的宿主机上已经定义了,docker-compose 会自动将其值传递给容器。

  • .env 文件中读取: 你可以在 docker-compose.yml 同目录下创建一个 .env 文件,并在其中定义所有环境变量。docker-compose 会自动读取该文件,并将其中的变量传递给容器。

例如,创建一个 .env 文件:

1
2
3
4
5
SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/my_database
SPRING_DATASOURCE_USERNAME=root
SPRING_DATASOURCE_PASSWORD=mysecretpassword
SPRING_REDIS_HOST=redis
SPRING_REDIS_PASSWORD=
1
2
3
4
5
6
    environment:
      - SPRING_DATASOURCE_URL
      - SPRING_DATASOURCE_USERNAME
      - SPRING_DATASOURCE_PASSWORD
      - SPRING_REDIS_HOST
      - SPRING_REDIS_PASSWORD

这里需要注意一点,这里的environment必须跟springboot的配置文件的配置名是(或者你自己程序所需要的环境变量)相同的

1
2
3
spring:
  datasource:
   url:

这里写要转成大写,并且中间使用_隔开。上面的就写成SPRING_DATASOURCE_URL。

注意:

如果你的.env文件配置的名字与springboot配置名相同可以直接写

1
2
environment:
  -SPRING_DATASOURCE_URL

但是如果不同,你需要声明式的进行赋值。

例如假如你在.env文件中写的是DATASOURCE_URL。

那么你就需要写成这样

1
2
environment:
  -SPRING_DATASOURCE_URL=DATASOURCE_URL

volumes 卷

左边是宿主机的目录,右边是容器的目录。中间用:隔开。

你可能想知道 假如你想为数据库指定数据存放的位置你可以直接在宿主机创建目录并指定,这很好理解。

但你如何知道这个文件要映射到容器的哪个位置?哪个路径是容器存放数据的地方?这里需要你自己去看官方的docker文档知晓

比如

1
2
3
    volumes:
      - ./data/mysql:/var/lib/mysql
      - ./sql/new_create-table_zx.sql:/docker-entrypoint-initdb.d/init.sql:ro
  • 将本地的 ./data/mysql 目录挂载到容器内的 /var/lib/mysql,用于持久化数据库数据,防止容器删除后数据丢失。
  • 将本地的 ./sql/new_create-table_zx.sql 文件挂载到容器内的 /docker-entrypoint-initdb.d/init.sql。这行很关键,它会让 MySQL 容器在首次启动时自动执行这个 SQL 脚本,用于创建表或初始化数据。

总结

为使用 Dockerfile 来构建单个服务的镜像,然后使用 Docker Compose 来协调这些镜像,将它们组合成一个完整的应用程序。

最后更新于 2025-09-23