|
3 | 3 |
|
4 | 4 | # docker compose stacks for wger
|
5 | 5 |
|
6 |
| -Contains 3 docker compose environments: |
| 6 | +The prod docker compose file starts up a production environment with the application |
| 7 | +server, a reverse proxy, a database, a caching server and a celery queue all |
| 8 | +configured. |
7 | 9 |
|
8 |
| -* prod (in root of this repository) |
9 |
| -* dev (uses sqlite) |
10 |
| -* dev-postgres (uses postgresql) |
| 10 | +Basically, just do `docker compose up -d`. For more details, consult the documentation: |
11 | 11 |
|
12 |
| -## Introduction |
13 |
| - |
14 |
| -The prod docker compose file starts up a production environment with gunicorn |
15 |
| -as the webserver, postgres as a database and redis for caching with nginx |
16 |
| -used as a reverse proxy. |
17 |
| - |
18 |
| -The two develop environments don't use redis (caching), celery (jobs) or nginx. |
19 |
| - |
20 |
| -The database, static files and uploaded images are mounted as volumes so |
21 |
| -the data is persisted. The only thing you need to do is update the docker |
22 |
| -images. Consult the docker volume command for details on how to access or |
23 |
| -backup this data. |
24 |
| - |
25 |
| -It is recommended to regularly pull the latest version of the images from this |
26 |
| -repository, since sometimes new configurations or environmental variables are |
27 |
| -added. |
28 |
| - |
29 |
| -# Production |
30 |
| - |
31 |
| -### Configuration |
32 |
| - |
33 |
| -Instead of editing the compose file or the env file directly, it is recommended |
34 |
| -to extend it. That way you can more easily pull changes from this repository. |
35 |
| - |
36 |
| -For example, you might not want to run the application on port 80 because some |
37 |
| -other service in your network is already using it. For this, simply create a new |
38 |
| -file called `docker-compose.override.yml` with the following content: |
39 |
| - |
40 |
| - services: |
41 |
| - nginx: |
42 |
| - ports: |
43 |
| - - "8080:80" |
44 |
| - |
45 |
| -Now the port setting will be overwritten from the configured nginx service when |
46 |
| -you do a `docker compose up`. However, note that compose will concatenate both sets |
47 |
| -of values so in this case the application will be binded to 8080 (from the override) |
48 |
| -*and* 80 (from the regular compose file). It seems that at the moment the only |
49 |
| -workaround is remove the ports settings altogether from the compose file. |
50 |
| - |
51 |
| -The same applies to the env variables, just create a new file called e.g. `my.env` |
52 |
| -and add it after the provided `prod.env` for the web service (again, this is |
53 |
| -`docker-compose.override.yml`). There you add the settings that you changed, and only |
54 |
| -those, which makes it easier to troubleshoot, etc.: |
55 |
| - |
56 |
| - web: |
57 |
| - env_file: |
58 |
| - - ./config/prod.env |
59 |
| - - ./config/my.env |
60 |
| - |
61 |
| -To add a web interface for the celery queue, add a new service to the override file: |
62 |
| - |
63 |
| - celery_flower: |
64 |
| - image: wger/server:latest |
65 |
| - container_name: wger_celery_flower |
66 |
| - command: /start-flower |
67 |
| - env_file: |
68 |
| - - ./config/prod.env |
69 |
| - ports: |
70 |
| - - "5555:5555" |
71 |
| - healthcheck: |
72 |
| - test: wget --no-verbose --tries=1 http://localhost:5555/healthcheck |
73 |
| - interval: 10s |
74 |
| - timeout: 5s |
75 |
| - retries: 5 |
76 |
| - depends_on: |
77 |
| - celery_worker: |
78 |
| - condition: service_healthy |
79 |
| - |
80 |
| -For more information and possibilities consult <https://docs.docker.com/compose/extends/> |
81 |
| - |
82 |
| -### 1 - Start |
83 |
| - |
84 |
| -1. Cd into the environment of your choice. |
85 |
| -2. To start all services: |
86 |
| - |
87 |
| - docker compose up -d |
88 |
| - |
89 |
| -Optionally download current exercises, exercise images and the ingredients |
90 |
| -from wger.de. Please note that `load-online-fixtures` will overwrite any local |
91 |
| -changes you might have while `sync-ingredients` should be used afterward once |
92 |
| -you have imported the initial fixtures: |
93 |
| - |
94 |
| - docker compose exec web python3 manage.py sync-exercises |
95 |
| - docker compose exec web python3 manage.py download-exercise-images |
96 |
| - docker compose exec web python3 manage.py download-exercise-videos |
97 |
| - |
98 |
| - # Loads a base set of ingredients |
99 |
| - docker compose exec web wger load-online-fixtures |
100 |
| - |
101 |
| - # optionally run this afterwards to sync all the ingredients (around 1GB, |
102 |
| - # this process takes a loooong time): |
103 |
| - docker compose exec web python3 manage.py sync-ingredients-async |
104 |
| - |
105 |
| -(these steps are configured by default to run regularly in the background, but |
106 |
| -can also run on startup as well, see the options in `prod.env`.) |
107 |
| - |
108 |
| - |
109 |
| -Then open <http://localhost> (or your server's IP) and log in as: **admin**, |
110 |
| -password **adminadmin** |
111 |
| - |
112 |
| - |
113 |
| -### 2 - Update the application |
114 |
| - |
115 |
| -Just remove the containers and pull the newest version: |
116 |
| - |
117 |
| - docker compose down |
118 |
| - docker compose pull |
119 |
| - docker compose up |
120 |
| - |
121 |
| -### 3 - Lifecycle Management |
122 |
| - |
123 |
| -To stop all services issue a stop command, this will preserve all containers |
124 |
| -and volumes: |
125 |
| - |
126 |
| - docker compose stop |
127 |
| - |
128 |
| -To start everything up again: |
129 |
| - |
130 |
| - docker compose start |
131 |
| - |
132 |
| -To remove all containers (except for the volumes) |
133 |
| - |
134 |
| - docker compose down |
135 |
| - |
136 |
| -To view the logs: |
137 |
| - |
138 |
| - docker compose logs -f |
139 |
| - |
140 |
| -You might need to issue other commands or do other manual work in the container, |
141 |
| -e.g. |
142 |
| - |
143 |
| - docker compose exec web yarn install |
144 |
| - docker compose exec --user root web /bin/bash |
145 |
| - docker compose exec --user postgres db psql wger -U wger |
146 |
| - |
147 |
| -## Deployment |
148 |
| - |
149 |
| -The easiest way to deploy this application to prod is to use a reverse proxy like |
150 |
| -nginx or traefik. You can change the port this application exposes and reverse proxy |
151 |
| -your domain to it. For this just edit the "nginx" service in docker-compose.yml and |
152 |
| -set the port to some value, e.g. `"8080:80"` then configure your proxy to forward |
153 |
| -requests to it, e.g. for nginx (no other ports need to be changed, they are used |
154 |
| -only within the application's docker network): |
155 |
| - |
156 |
| -Also notice that the application currently needs to run on its own (sub)domain |
157 |
| -and not in a subdirectory, so `location /wger {` will probably only mostly work. |
158 |
| - |
159 |
| - |
160 |
| -```nginx |
161 |
| -upstream wger { |
162 |
| - server 123.456.789.0:8080; |
163 |
| -} |
164 |
| -
|
165 |
| -server { |
166 |
| - listen 80; |
167 |
| - listen [::]:443 ssl; |
168 |
| - listen 443 ssl; |
169 |
| -
|
170 |
| - location / { |
171 |
| - proxy_pass http://wger; |
172 |
| - proxy_set_header Host $http_host; |
173 |
| - proxy_set_header X-Real-IP $remote_addr; |
174 |
| - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
175 |
| - proxy_set_header X-Forwarded-Proto $scheme; |
176 |
| - proxy_redirect off; |
177 |
| - } |
178 |
| -
|
179 |
| - server_name my.domain.example.com; |
180 |
| -
|
181 |
| - ssl_certificate /path/to/https/certificate.crt; |
182 |
| - ssl_certificate_key /path/to/https/certificate.key; |
183 |
| -} |
184 |
| -``` |
185 |
| - |
186 |
| -### If you get CSRF errors |
187 |
| - |
188 |
| -If you want to use HTTPS like in the example config you need to add some |
189 |
| -additional configurations. Since the HTTPS connections are reversed proxied, |
190 |
| -the secure connection terminates there, the application will receive a regular |
191 |
| -HTTP request and django's [CSRF protection](https://docs.djangoproject.com/en/4.1/ref/csrf/) |
192 |
| -will kick in. |
193 |
| - |
194 |
| -To solve this, update the env file and either |
195 |
| - |
196 |
| -* manually set a list of your domain names and/or server IPs |
197 |
| - `CSRF_TRUSTED_ORIGINS=https://my.domain.example.com,https://118.999.881.119:8008` |
198 |
| - If you are unsure what origin to add here, set the debug setting to true, restart |
199 |
| - and try again, the error message that appears will have the origin prominently |
200 |
| - displayed. Note: the port is important! |
201 |
| -* or set the `X-Forwarded-Proto` header like in the example and set |
202 |
| - `X_FORWARDED_PROTO_HEADER_SET=True`. If you do this consult the |
203 |
| - [documentation](https://docs.djangoproject.com/en/4.1/ref/settings/#secure-proxy-ssl-header) |
204 |
| - as there are some security considerations. |
205 |
| - |
206 |
| -You might want to set `DJANGO_DEBUG` to true while you are debugging this is you |
207 |
| -encounter errors. |
208 |
| - |
209 |
| - |
210 |
| -### Automatically start service |
211 |
| - |
212 |
| -If everything works correctly, you will want to start the compose file as a |
213 |
| -service so that it auto restarts when you reboot the server. If you use systemd, |
214 |
| -this can be done with a simple file. Create the file `/etc/systemd/system/wger.service` |
215 |
| -and enter the following content (check where the absolute path of the docker |
216 |
| -command is with `which docker`) |
217 |
| - |
218 |
| -``` |
219 |
| -[Unit] |
220 |
| -Description=wger docker compose service |
221 |
| -PartOf=docker.service |
222 |
| -After=docker.service |
223 |
| -
|
224 |
| -[Service] |
225 |
| -Type=oneshot |
226 |
| -RemainAfterExit=true |
227 |
| -WorkingDirectory=/path/to/the/docker/compose/ |
228 |
| -ExecStart=/usr/bin/docker compose up -d --remove-orphans |
229 |
| -ExecStop=/usr/bin/docker compose down |
230 |
| -
|
231 |
| -[Install] |
232 |
| -WantedBy=multi-user.target |
233 |
| -``` |
234 |
| - |
235 |
| -Read the file with `systemctl daemon-reload` and start it with |
236 |
| -`systemctl start wger`. If there are no errors and `systemctl status wger` |
237 |
| -shows that the service is active (this might take some time), everything went |
238 |
| -well. With `systemctl enable wger` the service will be automatically restarted |
239 |
| -after a reboot. |
240 |
| - |
241 |
| -### Backup |
242 |
| - |
243 |
| -**Database volume:** The most important thing to backup. For this just make |
244 |
| -a dump and restore it when needed |
245 |
| - |
246 |
| -``` |
247 |
| -# Stop all other containers so the db is not changed while you export it |
248 |
| -docker compose stop web nginx cache celery_worker celery_beat |
249 |
| -docker compose exec db pg_dumpall --clean --username wger > backup.sql |
250 |
| -docker compose start |
251 |
| -
|
252 |
| -# When you need to restore it |
253 |
| -docker compose stop |
254 |
| -docker volume remove docker_postgres-data |
255 |
| -docker compose up db |
256 |
| -cat backup.sql | docker compose exec -T db psql --username wger --dbname wger |
257 |
| -docker compose up |
258 |
| -``` |
259 |
| - |
260 |
| -**Media volume:** If you haven't uploaded any own images (exercises, gallery), |
261 |
| -you don't need to backup this, the contents can just be downloaded again. If |
262 |
| -you have, please consult these possibilities: |
263 |
| - |
264 |
| -* <https://www.docker.com/blog/back-up-and-share-docker-volumes-with-this-extension/> |
265 |
| -* <https://github.com/BretFisher/docker-vackup> |
266 |
| - |
267 |
| - |
268 |
| -**Static volume:** The contents of this volume are 100% generated and recreated |
269 |
| -on startup, no need to backup anything |
270 |
| - |
271 |
| -### Postgres Upgrade |
272 |
| - |
273 |
| -It is sadly not possible to automatically upgrade between postgres versions, |
274 |
| -you need to perform the upgrade manually. Since the amount of data the app |
275 |
| -generates is small a simple dump and restore is the simplest way to do this. |
276 |
| - |
277 |
| -If you pulled new changes from this repo and got the error message "The data |
278 |
| -directory was initialized by PostgreSQL version 12, which is not compatible |
279 |
| -with this version 15." this is for you. |
280 |
| - |
281 |
| -See also <https://github.com/docker-library/postgres/issues/37> |
282 |
| - |
283 |
| - |
284 |
| -```bash |
285 |
| -# Checkout the last version of the composer file that uses postgres 12 |
286 |
| -git checkout pg-12 |
287 |
| - |
288 |
| -# Stop all other containers |
289 |
| -docker compose stop web nginx cache celery_worker celery_beat |
290 |
| - |
291 |
| -# Make a dump of the database and remove the container and volume |
292 |
| -docker compose exec db pg_dumpall --clean --username wger > backup.sql |
293 |
| -docker compose stop db |
294 |
| -docker compose down |
295 |
| -docker volume remove docker_postgres-data |
296 |
| - |
297 |
| -# Checkout current version, import the dump and start everything |
298 |
| -git checkout master |
299 |
| -docker compose up db |
300 |
| -cat backup.sql | docker compose exec -T db psql --username wger --dbname wger |
301 |
| -docker compose exec -T db psql --username wger --dbname wger -c "ALTER USER wger WITH PASSWORD 'wger'" |
302 |
| -docker compose up |
303 |
| -rm backup.sql |
304 |
| -``` |
305 |
| - |
306 |
| -## Building |
307 |
| - |
308 |
| -If you want to build the images yourself, clone the wger repository and follow |
309 |
| -the instructions for the devel image in the `extras/docker` folder. |
310 |
| - |
311 |
| -# Development environments |
312 |
| - |
313 |
| -Note: the docker images assume a wger user id of 1000. Since we mount the code |
314 |
| -and write from the image into your code repository, you may run into permission errors |
315 |
| -if your user id is not 1000. We don't have a good solution for such situation yet. |
316 |
| -Check your user id with `echo $UID`. |
317 |
| - |
318 |
| -1. Clone https://github.com/wger-project/wger to a folder of your choice. |
319 |
| -2. `cd` into the environment of your choice (dev or dev-postgres) |
320 |
| -3. Copy `.env.example` to `.env` and set the path to correspond to the location where |
321 |
| - you have checked out the wger server git repo. |
322 |
| - |
323 |
| - |
324 |
| -```shell |
325 |
| -docker compose up |
326 |
| -docker compose exec web /bin/bash |
327 |
| -cp extras/docker/production/settings.py . |
328 |
| - |
329 |
| -wger bootstrap # this creates initial db tables, runs yarn install, yarn build:css:sass, etc |
330 |
| -python3 manage.py migrate # safe to ignore: Your models in app(s): 'exercises', 'nutrition' have changes that are not yet reflected in a migration, and so won't be applied. |
331 |
| -python3 manage.py sync-exercises # pull exercises from wger.de (or other source you have defined) |
332 |
| -wger load-online-fixtures # pull nutrition information |
333 |
| - |
334 |
| -# if you use sqlite, at this time you can make a backup if you want |
335 |
| -# such that if you mess something up, you don't have to start from scratch |
336 |
| -cp /home/wger/db/database.sqlite /home/wger/db/database.sqlite.orig |
337 |
| - |
338 |
| -# finally, this is important, start the actual server! |
339 |
| -python3 manage.py runserver 0.0.0.0:8000 |
340 |
| -``` |
341 |
| - |
342 |
| -You can now login on http://localhost:8000 - there is one user account: admin, with password adminadmin |
343 |
| -The server should restart automatically when you change code, etc. |
344 |
| - |
345 |
| -If you use `dev` you can use the `sqlite3` program to execute queries against the database file. |
346 |
| -For `postgres-sqlite` you can use `pgcli -h localhost -p 5432 -u wger` on your host, with password `wger` |
| 12 | +* prod: <https://wger.readthedocs.io/en/latest/production/docker.html> |
| 13 | +* dev: <https://wger.readthedocs.io/en/latest/development/docker.html> |
347 | 14 |
|
348 | 15 | ## Contact
|
349 | 16 |
|
|
0 commit comments