Skip to content

Commit bf4b09e

Browse files
darkweakdunglas
authored andcommitted
Update Traefik according to api-platform V2.4 docker-compose declaration (#837)
* Implements mercure and admin into traefik doc file then update with going further to define all in .env file * fix reviews
1 parent f57b813 commit bf4b09e

File tree

1 file changed

+261
-11
lines changed

1 file changed

+261
-11
lines changed

deployment/traefik.md

Lines changed: 261 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,38 @@ Override ports and add labels to tell Traefik to listen on the routes mentionned
1212

1313
`--api` Tells Traefik to generate a browser view to watch containers and IP/DNS associated easier
1414
`--docker` Tells Traefik to listen on Docker Api
15-
`--docker.domain=localhost` The main DNS will be on localhost
1615
`labels:` Key for Traefik configuration into Docker integration
1716
```yaml
1817
services:
1918
# ...
2019
api:
2120
labels:
22-
- "traefik.frontend.rule=Host:api.localhost"
21+
- traefik.frontend.rule=Host:api.localhost
2322
```
2423
The API DNS will be specified with `traefik.frontend.rule=Host:your.host` (here api.localhost)
2524

2625
`--traefik.port=3000` The port specified to Traefik will be exposed by the container (here the React app exposes the 3000 port)
2726

2827

2928
```yaml
29+
# docker-compose.yml
3030
version: '3.4'
3131
32+
x-cache:
33+
&cache
34+
cache_from:
35+
- ${CONTAINER_REGISTRY_BASE}/php
36+
- ${CONTAINER_REGISTRY_BASE}/nginx
37+
- ${CONTAINER_REGISTRY_BASE}/varnish
38+
39+
3240
services:
33-
reverse-proxy:
41+
traefik:
3442
image: traefik
35-
command: --api --docker --docker.domain=localhost
43+
command: --api --docker
3644
ports:
3745
- "80:80" #All HTTP access will be caught by Traefik
46+
- "443:443" #All HTTPS access will be caught by Traefik
3847
- "8080:8080" #Access Traefik webview
3948
volumes:
4049
- /var/run/docker.sock:/var/run/docker.sock
@@ -43,10 +52,10 @@ services:
4352
image: ${CONTAINER_REGISTRY_BASE}/php
4453
build:
4554
context: ./api
55+
target: api_platform_php
56+
<<: *cache
4657
depends_on:
4758
- db
48-
env_file:
49-
- ./api/.env
5059
# Comment out these volumes in production
5160
volumes:
5261
- ./api:/srv/api:rw,cached
@@ -56,20 +65,37 @@ services:
5665
api:
5766
image: ${CONTAINER_REGISTRY_BASE}/nginx
5867
labels:
59-
- "traefik.frontend.rule=Host:api.localhost"
68+
- traefik.frontend.rule=Host:api.localhost
6069
build:
6170
context: ./api
71+
target: api_platform_nginx
72+
<<: *cache
6273
depends_on:
6374
- php
6475
# Comment out this volume in production
6576
volumes:
6677
- ./api/public:/srv/api/public:ro
6778
79+
cache-proxy:
80+
image: ${CONTAINER_REGISTRY_BASE}/varnish
81+
build:
82+
context: ./api
83+
target: api_platform_varnish
84+
<<: *cache
85+
depends_on:
86+
- api
87+
volumes:
88+
- ./api/docker/varnish/conf:/usr/local/etc/varnish:ro
89+
tmpfs:
90+
- /usr/local/var/varnish:exec
91+
labels:
92+
- traefik.frontend.rule=Host:cache.localhost
93+
6894
db:
6995
# In production, you may want to use a managed database service
70-
image: postgres:9.6-alpine
96+
image: postgres:10-alpine
7197
labels:
72-
- "traefik.frontend.rule=Host:db.localhost"
98+
- traefik.frontend.rule=Host:db.localhost
7399
environment:
74100
- POSTGRES_DB=api
75101
- POSTGRES_USER=api-platform
@@ -82,12 +108,27 @@ services:
82108
ports:
83109
- "5432:5432"
84110
111+
mercure:
112+
# In production, you may want to use the managed version of Mercure, https://mercure.rocks
113+
image: dunglas/mercure
114+
environment:
115+
# You should definitely change all these values in production
116+
- JWT_KEY=!UnsecureChangeMe!
117+
- ALLOW_ANONYMOUS=1
118+
- CORS_ALLOWED_ORIGINS=*
119+
- PUBLISH_ALLOWED_ORIGINS=http://mercure.localhost
120+
- DEMO=1
121+
labels:
122+
- traefik.frontend.rule=Host:localhost
123+
85124
client:
86125
# Use a static website hosting service in production
87126
# See https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.mddeployment
88127
image: ${CONTAINER_REGISTRY_BASE}/client
89128
build:
90129
context: ./client
130+
cache_from:
131+
- ${CONTAINER_REGISTRY_BASE}/client
91132
env_file:
92133
- ./client/.env
93134
volumes:
@@ -96,8 +137,25 @@ services:
96137
expose:
97138
- 3000
98139
labels:
99-
- "traefik.port=3000"
100-
- "traefik.frontend.rule=Host:localhost"
140+
- traefik.port=3000
141+
- traefik.frontend.rule=Host:localhost
142+
143+
admin:
144+
# Use a static website hosting service in production
145+
# See https://facebook.github.io/create-react-app/docs/deployment
146+
image: ${CONTAINER_REGISTRY_BASE}/admin
147+
build:
148+
context: ./admin
149+
cache_from:
150+
- ${CONTAINER_REGISTRY_BASE}/admin
151+
volumes:
152+
- ./admin:/usr/src/admin:rw,cached
153+
- /usr/src/admin/node_modules
154+
expose:
155+
- 3000
156+
labels:
157+
- traefik.port=3000
158+
- traefik.frontend.rule=Host:admin.localhost
101159
102160
volumes:
103161
db-data: {}
@@ -120,3 +178,195 @@ If you do that, you'll have to update the `CORS_ALLOW_ORIGIN` environment variab
120178
## Known Issues
121179

122180
If your network is of type B, it may conflict with the Traefik sub-network.
181+
182+
## Going Further
183+
184+
As this Traefik configuration listens on 80 and 443 ports, you can run only 1 Traefik instance per server. However, you may want to run multiple API Platform projects on same server. To deal with it, you'll have to externalize the Traefik configuration to another `docker-compose.yml` file, anywhere on your server.
185+
Here is a working example:
186+
```yaml
187+
# /somewhere/docker-compose.yml
188+
version: '3.4'
189+
190+
services:
191+
traefik:
192+
image: traefik
193+
command: --api --docker
194+
ports:
195+
- "80:80"
196+
- "443:443"
197+
- "8080:8080"
198+
volumes:
199+
- /var/run/docker.sock:/var/run/docker.sock
200+
# load a TOML configuration file and to generate Let's Encrypt certificated as explained in https://docs.traefik.io/user-guide/docker-and-lets-encrypt/
201+
# - ./traefik.toml:/traefik.toml
202+
# - ./acme.json:/acme.json
203+
networks:
204+
- api_platform_network
205+
# Add other networks here
206+
207+
networks:
208+
api_platform_network:
209+
external: true
210+
# Add other networks here
211+
```
212+
213+
Then update the `docker-compose.yaml` file belonging to your API Platform projects:
214+
```patch
215+
# docker-compose.yml
216+
version: '3.4'
217+
218+
x-cache:
219+
&cache
220+
cache_from:
221+
- ${CONTAINER_REGISTRY_BASE}/php
222+
- ${CONTAINER_REGISTRY_BASE}/nginx
223+
- ${CONTAINER_REGISTRY_BASE}/varnish
224+
225+
+x-network:
226+
+ &network
227+
+ networks:
228+
+ - api_platform_network
229+
230+
services:
231+
# Uncomment these lines only if you want to run one api-platform instance using traefik
232+
- traefik:
233+
- image: traefik:latest
234+
- command: --api --docker
235+
- ports:
236+
- - "80:80"
237+
- - "443:443"
238+
- volumes:
239+
- - /var/run/docker.sock:/var/run/docker.sock
240+
- <<: *network
241+
242+
php:
243+
image: ${CONTAINER_REGISTRY_BASE}/php
244+
build:
245+
context: ./api
246+
target: api_platform_php
247+
<<: *cache
248+
depends_on:
249+
- db
250+
+ environment:
251+
+ # You should remove these variables from .env into api folder
252+
+ - TRUSTED_HOSTS=^(((${SUBDOMAINS_LIST}\.)?${DOMAIN_NAME})|api)$$
253+
+ - CORS_ALLOW_ORIGIN=^${HTTP_OR_SSL}(${SUBDOMAINS_LIST}.)?${DOMAIN_NAME}$$
254+
+ - DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@db/${DB_NAME}
255+
+ - MERCURE_SUBSCRIBE_URL=${HTTP_OR_SSL}mercure.${DOMAIN_NAME}$$
256+
+ - MERCURE_PUBLISH_URL=${HTTP_OR_SSL}mercure.${DOMAIN_NAME}$$
257+
+ - MERCURE_JWT_SECRET=${JWT_KEY}
258+
volumes:
259+
- ./api:/srv/api:rw,cached
260+
+ <<: *network
261+
262+
api:
263+
image: ${CONTAINER_REGISTRY_BASE}/nginx
264+
build:
265+
context: ./api
266+
target: api_platform_nginx
267+
<<: *cache
268+
depends_on:
269+
- php
270+
volumes:
271+
- ./api/public:/srv/api/public:ro
272+
labels:
273+
- traefik.frontend.rule=Host:api.${DOMAIN_NAME}
274+
+ <<: *network
275+
276+
cache-proxy:
277+
image: ${CONTAINER_REGISTRY_BASE}/varnish
278+
build:
279+
context: ./api
280+
target: api_platform_varnish
281+
<<: *cache
282+
depends_on:
283+
- api
284+
volumes:
285+
- ./api/docker/varnish/conf:/usr/local/etc/varnish:ro
286+
tmpfs:
287+
- /usr/local/var/varnish:exec
288+
labels:
289+
- traefik.frontend.rule=Host:cache.${DOMAIN_NAME}
290+
+ <<: *network
291+
292+
db:
293+
image: postgres:10-alpine
294+
environment:
295+
- POSTGRES_DB=${DB_NAME}
296+
- POSTGRES_USER=${DB_USER}
297+
- POSTGRES_PASSWORD=${DB_PASS}
298+
volumes:
299+
- db-data:/var/lib/postgresql/data:rw
300+
+ <<: *network
301+
302+
mercure:
303+
image: dunglas/mercure
304+
environment:
305+
- JWT_KEY=${JWT_KEY}
306+
- ALLOW_ANONYMOUS=0
307+
- CORS_ALLOWED_ORIGINS=^${HTTP_OR_SSL}(${SUBDOMAINS_LIST}.)?${DOMAIN_NAME}$$
308+
- PUBLISH_ALLOWED_ORIGINS=${HTTP_OR_SSL}
309+
- DEMO=1
310+
labels:
311+
- traefik.frontend.rule=Host:mercure.${DOMAIN_NAME}
312+
+ <<: *network
313+
314+
client:
315+
image: ${CONTAINER_REGISTRY_BASE}/client
316+
build:
317+
context: ./client
318+
cache_from:
319+
- ${CONTAINER_REGISTRY_BASE}/client
320+
volumes:
321+
- ./client:/usr/src/client:rw,cached
322+
- /usr/src/client/node_modules
323+
expose:
324+
- 3000
325+
labels:
326+
- traefik.frontend.rule=Host:${DOMAIN_NAME},www.${DOMAIN_NAME}
327+
- traefik.port=3000
328+
environment:
329+
# You should remove this variable from .env into client folder
330+
- REACT_APP_API_ENTRYPOINT=${HTTP_OR_SSL}api.${DOMAIN_NAME}
331+
+ <<: *network
332+
333+
admin:
334+
image: ${CONTAINER_REGISTRY_BASE}/admin
335+
build:
336+
context: ./admin
337+
cache_from:
338+
- ${CONTAINER_REGISTRY_BASE}/admin
339+
environment:
340+
# You should remove this variable from .env into admin folder
341+
- REACT_APP_API_ENTRYPOINT=${HTTP_OR_SSL}api.${DOMAIN_NAME}
342+
volumes:
343+
- ./admin:/usr/src/admin:rw,cached
344+
- /usr/src/admin/node_modules
345+
expose:
346+
- 3000
347+
labels:
348+
- traefik.frontend.rule=Host:admin.${DOMAIN_NAME}
349+
- traefik.port=3000
350+
+ <<: *network
351+
352+
volumes:
353+
db-data: {}
354+
355+
+networks:
356+
+ api_platform_network:
357+
+ external: true
358+
```
359+
360+
Finally, some environment variables must be defined, here is an example of a `.env` file to set them:
361+
```dotenv
362+
CONTAINER_REGISTRY_BASE=quay.io/api-platform
363+
DOMAIN_NAME=localhost
364+
HTTP_OR_SSL=http://
365+
DB_NAME=api-platform-db-name
366+
DB_PASS=YouMustChangeThisPassword
367+
DB_USER=api-platform
368+
JWT_KEY=!UnsecureChangeMe!
369+
SUBDOMAINS_LIST=(admin|api|cache|mercure|www)
370+
```
371+
372+
This way, you can configure your main variables into one single file.

0 commit comments

Comments
 (0)