前言:
前面我们讲了dockerfile文件用以构建镜像,然后通过镜像就能运行容器。
但是如果你要开发一个前后端网站你可能会需要Mysql、Redis、Nginx等,那么难道我们要一个一个的使用 docker run来创建容器并运行吗?这个时候我们就需要docker-compose了。
如果说dockerfile是构建单个镜像的脚本。
那么docker-compose就是一个可以用于定义和运行多容器 Docker 应用程序的工具。
Docker Compose 的核心概念
- 服务(Services): 一个服务代表一个应用程序容器。在
docker-compose.yml文件中,需要定义每个服务的镜像、端口映射、环境、卷挂载等配置。 - 网络(Networks): Docker Compose 会自动为你的应用程序创建一个默认网络,以便所有服务都能通过服务名称相互通信。
- 卷(Volumes): 卷用于持久化数据。你可以将数据库的数据目录挂载到宿主机上,这样即使容器被删除,数据也不会丢失。
使用Docker Compose
docker-compose.yml 示例
|
|
参数解析
注:已说明的不会重复说明
version: '3.8': 指定 Docker Compose 文件的版本。
networks: 定义了一个名为 my-network 的自定义网络,方便容器之间通信。
services: 定义了四个服务,web 、 server、mysql、redis。
服务名称可以自定义,之后容器通讯可以直接使用服务名。
注意:
由于每一个容器都有一个独立的网络环境。所以一般你的容器是访问不了别的容器的。
因此你需要一个容器的互联网来让容器互相交流。
因此如果你要使用前端nginx代理转发时不要写成 localhost:8123,而是应该直接写定义的server服务名。
web服务:
这是一个前端 Web 服务器。
image: 直接使用一个位于 GitHub 容器注册表(ghcr.io)的最新镜像,而不是从本地构建。ports: 将容器内的 80 和 403 端口映射到宿主机的 80 和 403 端口,用于外部访问。restart: always: 确保容器在退出时会自动重启。
server 服务
这是一个后端服务器。
build: 使用./app目录下的 Dockerfile 文件构建的镜像。depends_on: 声明此服务依赖mysql和redis(就是你自定义的服务名)服务,确保它们在server服务启动前就绪。environment: 定义了一系列环境变量,用于配置数据库和 Redis 的连接信息。这些变量需要在运行容器时进行设置。
mysql 服务
这是一个 MySQL 数据库服务。
environment: 定义了数据库的根密码和默认数据库名称。
**redis服务 **
这是一个 Redis 缓存服务。
image: 使用轻量级的redis:alpine镜像。restart: always: 容器退出时自动重启
这里着重说一下environment和volumes。
environment 环境
工作原理:当 Docker Compose 启动一个服务时,它会读取 environment 字段中定义的键值对,并将它们作为环境变量传递给该服务所运行的容器。
那么这些环境变量在哪里来的?
- 直接在
docker-compose.yml中赋值:
|
|
-
从宿主机的环境变量中继承: 如果
SPRING_DATASOURCE_URL在运行docker-compose up的宿主机上已经定义了,docker-compose会自动将其值传递给容器。 -
从
.env文件中读取: 你可以在docker-compose.yml同目录下创建一个.env文件,并在其中定义所有环境变量。docker-compose会自动读取该文件,并将其中的变量传递给容器。
例如,创建一个 .env 文件:
|
|
|
|
这里需要注意一点,这里的environment必须跟springboot的配置文件的配置名是(或者你自己程序所需要的环境变量)相同的。
|
|
这里写要转成大写,并且中间使用_隔开。上面的就写成SPRING_DATASOURCE_URL。
注意:
如果你的.env文件配置的名字与springboot配置名相同可以直接写
1 2environment: -SPRING_DATASOURCE_URL但是如果不同,你需要声明式的进行赋值。
例如假如你在.env文件中写的是DATASOURCE_URL。
那么你就需要写成这样
1 2environment: -SPRING_DATASOURCE_URL=DATASOURCE_URL
volumes 卷
左边是宿主机的目录,右边是容器的目录。中间用:隔开。
你可能想知道 假如你想为数据库指定数据存放的位置你可以直接在宿主机创建目录并指定,这很好理解。
但你如何知道这个文件要映射到容器的哪个位置?哪个路径是容器存放数据的地方?这里需要你自己去看官方的docker文档知晓。
比如
|
|
- 将本地的
./data/mysql目录挂载到容器内的/var/lib/mysql,用于持久化数据库数据,防止容器删除后数据丢失。 - 将本地的
./sql/new_create-table_zx.sql文件挂载到容器内的/docker-entrypoint-initdb.d/init.sql。这行很关键,它会让 MySQL 容器在首次启动时自动执行这个 SQL 脚本,用于创建表或初始化数据。
总结
为使用 Dockerfile 来构建单个服务的镜像,然后使用 Docker Compose 来协调这些镜像,将它们组合成一个完整的应用程序。