Skip to content

Commit ff6ad7a

Browse files
committed
♻️ Separate prod deployment into main Docker Compose file plus deploy Docker Compose
1 parent 76e3cfb commit ff6ad7a

7 files changed

Lines changed: 70 additions & 49 deletions

File tree

.github/workflows/deploy-production.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ jobs:
3434
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
3535
with:
3636
persist-credentials: false
37-
- run: docker compose -f compose.yml build
38-
- run: docker compose -f compose.yml up -d
37+
- run: docker compose -f compose.yml -f compose.deploy.yml build
38+
- run: docker compose -f compose.yml -f compose.deploy.yml up -d

.github/workflows/deploy-staging.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ jobs:
3434
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
3535
with:
3636
persist-credentials: false
37-
- run: docker compose -f compose.yml build
38-
- run: docker compose -f compose.yml up -d
37+
- run: docker compose -f compose.yml -f compose.deploy.yml build
38+
- run: docker compose -f compose.yml -f compose.deploy.yml up -d

compose.deploy.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
services:
2+
3+
proxy:
4+
restart: always
5+
ports:
6+
# Listen on port 80, default for HTTP, necessary to redirect to HTTPS
7+
- "80:80"
8+
# Listen on port 443, default for HTTPS
9+
- "443:443"
10+
volumes:
11+
# Mount the volume to store the certificates
12+
- traefik-certificates:/certificates
13+
command:
14+
# Enable Docker in Traefik, so that it reads labels from Docker services
15+
- --providers.docker
16+
# Do not expose all Docker services, only the ones explicitly exposed
17+
- --providers.docker.exposedbydefault=false
18+
# Create an entrypoint "http" listening on port 80
19+
- --entrypoints.http.address=:80
20+
# Redirect all HTTP traffic to HTTPS
21+
- --entrypoints.http.http.redirections.entrypoint.to=https
22+
- --entrypoints.http.http.redirections.entrypoint.scheme=https
23+
# Create an entrypoint "https" listening on port 443
24+
- --entrypoints.https.address=:443
25+
# Store the Let's Encrypt certificates in the mounted volume
26+
- --certificatesresolvers.le.acme.storage=/certificates/acme.json
27+
# Use the TLS Challenge for Let's Encrypt
28+
- --certificatesresolvers.le.acme.tlschallenge=true
29+
# Enable the access log, with HTTP requests
30+
- --accesslog
31+
# Enable the Traefik log, for configurations and errors
32+
- --log
33+
34+
db:
35+
restart: always
36+
37+
adminer:
38+
restart: always
39+
labels:
40+
# Route HTTPS traffic for the Adminer subdomain
41+
- traefik.http.routers.adminer-https.rule=Host(`adminer.${DOMAIN?Variable not set}`)
42+
- traefik.http.routers.adminer-https.entrypoints=https
43+
- traefik.http.routers.adminer-https.tls=true
44+
# Use the Let's Encrypt resolver
45+
- traefik.http.routers.adminer-https.tls.certresolver=le
46+
47+
backend:
48+
restart: always
49+
labels:
50+
# Route HTTPS traffic for this domain
51+
- traefik.http.routers.backend-https.rule=Host(`${DOMAIN?Variable not set}`)
52+
- traefik.http.routers.backend-https.entrypoints=https
53+
- traefik.http.routers.backend-https.tls=true
54+
# Use the Let's Encrypt resolver
55+
- traefik.http.routers.backend-https.tls.certresolver=le
56+
57+
volumes:
58+
# Create a volume to store the certificates, even if the container is recreated
59+
traefik-certificates:

compose.override.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ services:
66
# DOMAIN=localhost.tiangolo.com
77
proxy:
88
image: traefik:3.6
9-
restart: "no"
109
ports:
1110
- "80:80"
1211
- "8090:8080"
@@ -18,8 +17,6 @@ services:
1817
- --providers.docker.exposedbydefault=false
1918
# Create an entrypoint "http" listening on port 80
2019
- --entrypoints.http.address=:80
21-
# Create an entrypoint "https" listening on port 443
22-
- --entrypoints.https.address=:443
2320
# Enable the access log, with HTTP requests
2421
- --accesslog
2522
# Enable the Traefik log, for configurations and errors
@@ -31,17 +28,14 @@ services:
3128
# Enable the Dashboard and API in insecure mode for local development
3229
- --api.insecure=true
3330
db:
34-
restart: "no"
3531
ports:
3632
- "5432:5432"
3733

3834
adminer:
39-
restart: "no"
4035
ports:
4136
- "8080:8080"
4237

4338
backend:
44-
restart: "no"
4539
ports:
4640
- "8000:8000"
4741
build:

compose.yml

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,23 @@ services:
22

33
proxy:
44
image: traefik:3.6
5-
restart: always
6-
ports:
7-
# Listen on port 80, default for HTTP, necessary to redirect to HTTPS
8-
- "80:80"
9-
# Listen on port 443, default for HTTPS
10-
- "443:443"
115
volumes:
126
# Add Docker as a mounted volume, so that Traefik can read the labels of other services
137
- /var/run/docker.sock:/var/run/docker.sock:ro
14-
# Mount the volume to store the certificates
15-
- traefik-certificates:/certificates
168
command:
179
# Enable Docker in Traefik, so that it reads labels from Docker services
1810
- --providers.docker
1911
# Do not expose all Docker services, only the ones explicitly exposed
2012
- --providers.docker.exposedbydefault=false
2113
# Create an entrypoint "http" listening on port 80
2214
- --entrypoints.http.address=:80
23-
# Redirect all HTTP traffic to HTTPS
24-
- --entrypoints.http.http.redirections.entrypoint.to=https
25-
- --entrypoints.http.http.redirections.entrypoint.scheme=https
26-
# Create an entrypoint "https" listening on port 443
27-
- --entrypoints.https.address=:443
28-
# Store the Let's Encrypt certificates in the mounted volume
29-
- --certificatesresolvers.le.acme.storage=/certificates/acme.json
30-
# Use the TLS Challenge for Let's Encrypt
31-
- --certificatesresolvers.le.acme.tlschallenge=true
3215
# Enable the access log, with HTTP requests
3316
- --accesslog
3417
# Enable the Traefik log, for configurations and errors
3518
- --log
3619

3720
db:
3821
image: postgres:18
39-
restart: always
4022
healthcheck:
4123
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
4224
interval: 10s
@@ -54,7 +36,6 @@ services:
5436

5537
adminer:
5638
image: adminer
57-
restart: always
5839
depends_on:
5940
- db
6041
environment:
@@ -65,12 +46,6 @@ services:
6546
# Route HTTP traffic for the Adminer subdomain
6647
- traefik.http.routers.adminer-http.rule=Host(`adminer.${DOMAIN?Variable not set}`)
6748
- traefik.http.routers.adminer-http.entrypoints=http
68-
# Route HTTPS traffic for the Adminer subdomain
69-
- traefik.http.routers.adminer-https.rule=Host(`adminer.${DOMAIN?Variable not set}`)
70-
- traefik.http.routers.adminer-https.entrypoints=https
71-
- traefik.http.routers.adminer-https.tls=true
72-
# Use the Let's Encrypt resolver
73-
- traefik.http.routers.adminer-https.tls.certresolver=le
7449
# Define the port inside of the Docker service to use
7550
- traefik.http.services.adminer.loadbalancer.server.port=8080
7651

@@ -107,7 +82,6 @@ services:
10782

10883
backend:
10984
image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}'
110-
restart: always
11185
depends_on:
11286
db:
11387
condition: service_healthy
@@ -155,13 +129,5 @@ services:
155129
- traefik.http.routers.backend-http.rule=Host(`${DOMAIN?Variable not set}`)
156130
- traefik.http.routers.backend-http.entrypoints=http
157131

158-
# Route HTTPS traffic for this domain
159-
- traefik.http.routers.backend-https.rule=Host(`${DOMAIN?Variable not set}`)
160-
- traefik.http.routers.backend-https.entrypoints=https
161-
- traefik.http.routers.backend-https.tls=true
162-
# Use the Let's Encrypt resolver
163-
- traefik.http.routers.backend-https.tls.certresolver=le
164132
volumes:
165133
app-db-data:
166-
# Create a volume to store the certificates, even if the container is recreated
167-
traefik-certificates:

deployment.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
You can deploy the project using Docker Compose to a remote server.
44

5-
The production Docker Compose configuration includes Traefik to handle HTTPS and route incoming traffic to the application.
5+
The deployment Docker Compose configuration includes Traefik to handle HTTPS and route incoming traffic to the application.
66

77
You can use CI/CD (continuous integration and continuous deployment) systems to deploy automatically, there are already configurations to do it with GitHub Actions.
88

@@ -112,11 +112,11 @@ With the environment variables in place, you can deploy with Docker Compose:
112112

113113
```bash
114114
cd /root/code/app/
115-
docker compose -f compose.yml build
116-
docker compose -f compose.yml up -d
115+
docker compose -f compose.yml -f compose.deploy.yml build
116+
docker compose -f compose.yml -f compose.deploy.yml up -d
117117
```
118118

119-
For production you wouldn't want to have the overrides in `compose.override.yml`, that's why we explicitly specify `compose.yml` as the file to use.
119+
The `compose.deploy.yml` file adds the deployment settings to the shared configuration in `compose.yml`, including HTTPS and automatic certificate handling. Explicitly listing these files also excludes the local development settings in `compose.override.yml`.
120120

121121
## Continuous Deployment (CD)
122122

development.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,16 @@ After you update it, run again:
9797
docker compose watch
9898
```
9999

100-
Traefik is included in the main Docker Compose file. The development overrides enable its local dashboard and disable the production HTTPS configuration so you can test the domain with `localhost.tiangolo.com`.
100+
Traefik is included in the main Docker Compose file. The development overrides expose its local dashboard so you can inspect the routes used with `localhost.tiangolo.com`.
101101

102102
## Docker Compose files and env vars
103103

104104
There is a main `compose.yml` file with all the configurations that apply to the whole stack, it is used automatically by `docker compose`.
105105

106106
And there's also a `compose.override.yml` with overrides for development, for example to mount the source code as a volume. It is used automatically by `docker compose` to apply overrides on top of `compose.yml`.
107107

108+
The `compose.deploy.yml` file contains the deployment-specific settings, including HTTPS and automatic certificate handling. It is explicitly combined with `compose.yml` when deploying the application.
109+
108110
These Docker Compose files use the `.env` file containing configurations to be injected as environment variables in the containers.
109111

110112
They also use some additional configurations taken from environment variables set in the scripts before calling the `docker compose` command.

0 commit comments

Comments
 (0)