如果将服务都写在一个 docker-compose.yml 文件里面,那么服务之间可以使用 <服务名>:<端口> 的形式互相访问。
比如下面的 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
| services:
caddy:
image: caddy:alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- $PWD/config:/etc/caddy
- caddy_data:/data
- caddy_config:/config
miniflux:
image: miniflux/miniflux:latest
container_name: miniflux
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=test123
- BASE_URL=https://miniflux.example.site
db:
image: postgres:15
container_name: postgres
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=secret
volumes:
- miniflux-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
volumes:
caddy_data:
caddy_config:
miniflux-db:
|
想通过 Caddy 反向代理本地的 Miniflux,只需将 Caddyfile 配置如下:
1
2
3
4
5
6
7
8
9
10
| {
http_port 80
https_port 443
email example@email.site
}
miniflux.example.site {
encode zstd gzip
reverse_proxy miniflux:8080
}
|
文件列表:
1
2
3
4
| .
├── config
│ └── Caddyfile
└── docker-compose.yml
|
但是这样的 Docker Compose 是将所有的服务捆绑在了一起。如果后期想要再添加一个本地服务交给 Caddy 反向代理,又或者想删除某一个服务,是比较麻烦的。
不同 Docker Compose 文件启动的容器,默认会使用带文件夹名前缀的网络来隔离它们的信息,它们之间默认不能用服务名称访问。要实现多个 Docker Compose 文件启动的容器网络互通,需要配置 networks 指令。
首先使用 docker network create 命令手动创建网络。
1
| docker network create caddy_network
|
然后在Caddy 的 docker-compose.yml 配置好 netwroks:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| services:
caddy:
image: caddy:alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- $PWD/config:/etc/caddy
- caddy_data:/data
- caddy_config:/config
networks:
- caddy_network
volumes:
caddy_data:
caddy_config:
networks:
caddy_network:
external: true
|
external 参数表示使用已有的外部网络,而不是新建带文件夹名前缀的网络。
同样配置好 Miniflux 的 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
| services:
miniflux:
image: miniflux/miniflux:latest
container_name: miniflux
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=test123
- BASE_URL=https://miniflux.example.site
networks:
- database_network
- caddy_network
db:
image: postgres:15
container_name: postgres
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=secret
volumes:
- miniflux-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
networks:
- database_network
volumes:
miniflux-db:
networks:
database_network: # Provide the communication between miniflux and database only
internal: true
caddy_network:
external: true
|
Caddyfile 的配置不需要改变:
1
2
3
4
5
6
7
8
9
10
| {
http_port 80
https_port 443
email example@email.site
}
miniflux.example.site {
encode zstd gzip
reverse_proxy miniflux:8080
}
|
文件列表:
1
2
3
4
5
6
7
| .
├── miniflux
│ └── docker-compose.yml
└── caddy
├── config
│ └── Caddyfile
└── docker-compose.yml
|
这样避免了 Miniflux 示例文档 中暴露 8080 端口的做法,使用更安全的 https,也不用将 Miniflux 和 Caddy 绑定在同一个 Docker Compose 文件中。
上面的例子中 volumes 挂载了 Caddyfile 所在的文件夹,而不是只挂载 Caddyfile 文件,这是为了更好的将主机文件的更新实时反映到容器。File mount does not update with changes from host 讨论了这个问题。
简单来说,Docker 的绑定挂载基于 inode,Vim 等编辑器修改文件时,不是直接在原文件上直接修改,而是复制了一个原文件的副本,保存时用副本替换掉原文件,副本的 inode 和原文件不一样。
服务运行时,如果在主机里修改了 Caddyfile,下面的命令可以平滑重启 Caddy 服务:
1
2
3
4
| # 格式化 Caddyfile
docker container exec -it caddy caddy fmt --overwrite /etc/caddy/Caddyfile
# 更新 Caddyfile 并重启
docker container exec -it caddy caddy reload --config /etc/caddy/Caddyfile
|