Projekt

Allgemein

Profil

Setup erpnext15 dockerized » Historie » Version 34

Jeremias Keihsler, 04.05.2026 12:20

1 1 Jeremias Keihsler
h1. Setup erpnext15 dockerized 
2
3
the basic idea is taken from https://www.youtube.com/watch?v=8Q5B7DnxmLg
4
5
use of docker compose v2
6
7 31 Jeremias Keihsler
h2. vanilla install OS
8
9
take this with a grain of salt, as this is chapter is based on notes I found on my desk .. ;-)
10
11
h3. ssh & IP
12
13
* install ssh according to wiki
14
* nmtui set IP and gateway
15
* allow 8080
16
* enable ufw
17
18
h3. docker compose v2
19
20
sudo apt install ca-certification curl gnupg
21
add keyrnd+repo ???
22
sudo apt install docker-ce ... docker-compose-plugin
23
24
h3. vim & xtop
25
26
sudo apt install vim
27
sudo apt install htop
28
sudo apt install iotop
29
30
h3. erpnext
31
32
mkdir /opt/docker.compose/erpnext
33
34 33 Jeremias Keihsler
h2. download pwd.yml (version erpnext:v15.106.0)
35 1 Jeremias Keihsler
36 12 Jeremias Keihsler
https://github.com/frappe/frappe_docker/blob/7d4d0b18f4f1ad318b9d70b71fd229eff3c6874e/pwd.yml
37 1 Jeremias Keihsler
38
save in @/opt/docker.compose/erpnext@ as @docker-compose.yml@
39
40
<pre><code class="yaml">
41
services:
42
  backend:
43 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
44 2 Jeremias Keihsler
    networks:
45
      - frappe_network
46 1 Jeremias Keihsler
    deploy:
47
      restart_policy:
48
        condition: on-failure
49
    volumes:
50
      - sites:/home/frappe/frappe-bench/sites
51
      - logs:/home/frappe/frappe-bench/logs
52 2 Jeremias Keihsler
    environment:
53
      DB_HOST: db
54
      DB_PORT: "3306"
55
      MYSQL_ROOT_PASSWORD: admin
56 1 Jeremias Keihsler
      MARIADB_ROOT_PASSWORD: admin
57
58
  configurator:
59 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
60 2 Jeremias Keihsler
    networks:
61
      - frappe_network
62 1 Jeremias Keihsler
    deploy:
63
      restart_policy:
64
        condition: none
65
    entrypoint:
66
      - bash
67
      - -c
68
    command:
69
      - >
70
        ls -1 apps > sites/apps.txt;
71
        bench set-config -g db_host $$DB_HOST;
72
        bench set-config -gp db_port $$DB_PORT;
73
        bench set-config -g redis_cache "redis://$$REDIS_CACHE";
74
        bench set-config -g redis_queue "redis://$$REDIS_QUEUE";
75 2 Jeremias Keihsler
        bench set-config -g redis_socketio "redis://$$REDIS_QUEUE";
76 1 Jeremias Keihsler
        bench set-config -gp socketio_port $$SOCKETIO_PORT;
77
    environment:
78
      DB_HOST: db
79
      DB_PORT: "3306"
80
      REDIS_CACHE: redis-cache:6379
81
      REDIS_QUEUE: redis-queue:6379
82
      SOCKETIO_PORT: "9000"
83
    volumes:
84
      - sites:/home/frappe/frappe-bench/sites
85
      - logs:/home/frappe/frappe-bench/logs
86
87
  create-site:
88 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
89 2 Jeremias Keihsler
    networks:
90
      - frappe_network
91 1 Jeremias Keihsler
    deploy:
92
      restart_policy:
93
        condition: none
94
    volumes:
95
      - sites:/home/frappe/frappe-bench/sites
96
      - logs:/home/frappe/frappe-bench/logs
97
    entrypoint:
98
      - bash
99
      - -c
100
    command:
101
      - >
102
        wait-for-it -t 120 db:3306;
103
        wait-for-it -t 120 redis-cache:6379;
104
        wait-for-it -t 120 redis-queue:6379;
105
        export start=`date +%s`;
106
        until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \
107
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \
108
          [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]];
109
        do
110
          echo "Waiting for sites/common_site_config.json to be created";
111
          sleep 5;
112
          if (( `date +%s`-start > 120 )); then
113
            echo "could not find sites/common_site_config.json with required keys";
114
            exit 1
115
          fi
116
        done;
117
        echo "sites/common_site_config.json found";
118 2 Jeremias Keihsler
        bench new-site --mariadb-user-host-login-scope='%' --admin-password=admin --db-root-username=root --db-root-password=admin --install-app erpnext --set-default erpnext;
119 1 Jeremias Keihsler
120
  db:
121
    image: mariadb:10.6
122 2 Jeremias Keihsler
    networks:
123
      - frappe_network
124 1 Jeremias Keihsler
    healthcheck:
125
      test: mysqladmin ping -h localhost --password=admin
126
      interval: 1s
127 2 Jeremias Keihsler
      retries: 20
128 1 Jeremias Keihsler
    deploy:
129
      restart_policy:
130
        condition: on-failure
131
    command:
132
      - --character-set-server=utf8mb4
133
      - --collation-server=utf8mb4_unicode_ci
134
      - --skip-character-set-client-handshake
135
      - --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
136
    environment:
137
      MYSQL_ROOT_PASSWORD: admin
138
      MARIADB_ROOT_PASSWORD: admin
139
    volumes:
140
      - db-data:/var/lib/mysql
141
142
  frontend:
143 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
144 2 Jeremias Keihsler
    networks:
145
      - frappe_network
146
    depends_on:
147
      - websocket
148 1 Jeremias Keihsler
    deploy:
149
      restart_policy:
150
        condition: on-failure
151
    command:
152
      - nginx-entrypoint.sh
153
    environment:
154
      BACKEND: backend:8000
155
      FRAPPE_SITE_NAME_HEADER: erpnext
156
      SOCKETIO: websocket:9000
157
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
158
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
159
      UPSTREAM_REAL_IP_RECURSIVE: "off"
160
      PROXY_READ_TIMEOUT: 120
161
      CLIENT_MAX_BODY_SIZE: 50m
162
    volumes:
163
      - sites:/home/frappe/frappe-bench/sites
164
      - logs:/home/frappe/frappe-bench/logs
165
    ports:
166
      - "80:8080"
167
168
  queue-long:
169 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
170 2 Jeremias Keihsler
    networks:
171
      - frappe_network
172 1 Jeremias Keihsler
    deploy:
173
      restart_policy:
174
        condition: on-failure
175
    command:
176
      - bench
177
      - worker
178
      - --queue
179 2 Jeremias Keihsler
      - long,default,short
180 1 Jeremias Keihsler
    volumes:
181
      - sites:/home/frappe/frappe-bench/sites
182
      - logs:/home/frappe/frappe-bench/logs
183
184
  queue-short:
185 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
186 2 Jeremias Keihsler
    networks:
187
      - frappe_network
188 1 Jeremias Keihsler
    deploy:
189
      restart_policy:
190
        condition: on-failure
191
    command:
192
      - bench
193
      - worker
194
      - --queue
195 2 Jeremias Keihsler
      - short,default
196 1 Jeremias Keihsler
    volumes:
197
      - sites:/home/frappe/frappe-bench/sites
198
      - logs:/home/frappe/frappe-bench/logs
199
200
  redis-queue:
201
    image: redis:6.2-alpine
202 2 Jeremias Keihsler
    networks:
203
      - frappe_network
204 1 Jeremias Keihsler
    deploy:
205
      restart_policy:
206
        condition: on-failure
207
    volumes:
208
      - redis-queue-data:/data
209
210
  redis-cache:
211
    image: redis:6.2-alpine
212 2 Jeremias Keihsler
    networks:
213
      - frappe_network
214 1 Jeremias Keihsler
    deploy:
215
      restart_policy:
216
        condition: on-failure
217
218
  scheduler:
219 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
220 2 Jeremias Keihsler
    networks:
221
      - frappe_network
222 1 Jeremias Keihsler
    deploy:
223
      restart_policy:
224
        condition: on-failure
225
    command:
226
      - bench
227
      - schedule
228
    volumes:
229
      - sites:/home/frappe/frappe-bench/sites
230
      - logs:/home/frappe/frappe-bench/logs
231
232
  websocket:
233 33 Jeremias Keihsler
    image: frappe/erpnext:v15.106.0
234 2 Jeremias Keihsler
    networks:
235
      - frappe_network
236 1 Jeremias Keihsler
    deploy:
237
      restart_policy:
238
        condition: on-failure
239
    command:
240
      - node
241
      - /home/frappe/frappe-bench/apps/frappe/socketio.js
242
    volumes:
243
      - sites:/home/frappe/frappe-bench/sites
244
      - logs:/home/frappe/frappe-bench/logs
245
246
volumes:
247
  db-data:
248
  redis-queue-data:
249
  sites:
250
  logs:
251 2 Jeremias Keihsler
252
networks:
253
  frappe_network:
254
    driver: bridge
255 1 Jeremias Keihsler
</code></pre>
256
257
h2. usage of mounts instead of docker-volumes
258
259
didn't work for me .. mariadb yes, but erpnext no
260
261
h3. create directory structure
262
263
<pre><code class="shell">
264
mkdir -p /opt/docker.compose/erpnext/{c_db/var/lib/mysql,c_erp/home/frappe/frappe-bench/sites,c_erp/home/frappe/frappe-bench/logs,c_redis_cache/data,c_redis_queue/data,c_redis_socketio/data}
265
chmod -R g+w /opt/docker.compose/erpnext/c_*
266
chmod -R o+w /opt/docker.compose/erpnext/c_*
267
</code></pre>
268
269
fix permission issue within volume
270
271
<pre><code class="shell">
272
sudo docker exec --user root -it erpnext-backend-1 /bin/bash
273
chown -R frappe:frappe logs
274
chown -R frappe:frappe sites
275
</code></pre>
276
277
as a consequence stuck with volumes. Although they can be easily accessed from within the host.
278
279
h2. migrate erpnext from different server
280
281
https://discuss.frappe.io/t/moving-to-docker/80457/4
282
283
Take @bench --site {site-name} backup --with-files@ on the running setup.
284
Copy files from @sites/{site-name}/private/backups@ to new server and optionally stop old server so users don’t create new data.
285
In case of container setup copy files from server into container using docker cp or placing files in volume location.
286
If existing site matches new site ... drop site first (https://frappeframework.com/docs/user/en/bench/reference/drop-site)
287
@bench drop-site erpnext --db-root-password admin@
288
Enter any worker container and create site using @bench new-site --no-mariadb-socket@ command. Name the site as per configured domain name. (Note down the db_name from site_config.json created)
289
@bench new-site erpnext --no-mariadb-socket --verbose --db-root-password admin@
290
Enter mariadb container / use mysql client and execute drop database {db_name}; create database {db_name}. This will clean the site db that was created by new site. We do this so that we have a running site configured without any database resulting in Internal Server Error.
291
292
<pre><code class="shell">
293
sudo docker exec -it erpnext-db-1 /bin/bash
294
mysql -p
295
  show database;
296
  drop database _76e6a5f706540e85;
297
  create database _76e6a5f706540e85;
298
</code></pre>
299
300
    In mysql shell execute, @use {db_name}; source /path/to/database.sql@. This will restore the database from backup on fresh db. We use source from mysql shell as it re-connects in case of disconnection or timeout during restoration of huge database. Simple alternate command will be mysql -uroot -p{root-password} -h{hostname} {db_name} < /path/to/database.sql
301
    Copy additional keys and encryption_key from backed up site_config.json. (Note, DO NOT change the db_name, db_password keys from newly created site, only copy other keys from backup site_config) The keys are important for the email-service, the hostname is important to 'wkhtmltopdf'
302
303
and don't forget ..
304
305
<pre><code class="shell">
306
bench --site erpnext migrate
307
</code></pre>
308
309
copy the tar-ed files into the corresponding directories
310
311
h2. erpnext as a service
312
313
https://stackoverflow.com/questions/43671482/how-to-run-docker-compose-up-d-at-system-start-up
314
315
<pre>
316
# /etc/systemd/system/docker-compose-erpnext.service 
317
318
[Unit]
319
Description=Docker Compose Application Service (erpnext)
320
Requires=docker.service
321
After=docker.service
322
323
[Service]
324
Type=oneshot
325
RemainAfterExit=yes
326
WorkingDirectory=/opt/docker.compose/erpnext
327
ExecStart=/usr/bin/docker compose up -d
328
ExecStop=/usr/bin/docker compose down
329
TimeoutStartSec=0
330
331
[Install]
332
WantedBy=multi-user.target
333
</pre>
334
335
<pre><code class="shell">
336
systemctl enable docker-compose-app
337
</code></pre>
338
339
h2. backup erpnext from outside a container
340
341
<pre><code class="shell">
342
sudo docker exec -t erpnext-backend-1 /usr/local/bin/bench --site all backup --with-files
343
</code></pre>
344
345
h1. upgrade erpnext v15
346
347
h2. shutdown erpnext
348
349
<pre><code class="shell">
350
sudo systemctl stop docker-compose-erpnext
351
</code></pre>
352
353
h2. modify compose-file
354
355
<pre><code class="shell">
356
sudo vim /opt/docker.compose/erpnext/docker-compose.yml
357
</code></pre>
358
359 34 Jeremias Keihsler
replace all @frappe/erpnext:v15.88.0@ with the version desired (e.g. @v15.106.0@)
360 1 Jeremias Keihsler
361
check whether mariadb-version or redis-version should be changed as well. (e.g. @mariadb 10.6@ / @redis-6.2@)
362
363
h2. restart erpnext manually
364
365
<pre><code class="shell">
366
cd /opt/docker.compose/erpnext/
367
sudo docker compose up
368
</code></pre>
369
370
h2. migrate erpnext installation (from within any erpnext-container)
371
372
<pre><code class="shell">
373
sudo docker ps
374 13 Jeremias Keihsler
sudo docker exec -it erpnext-backend-1 /bin/bash
375 1 Jeremias Keihsler
bench --site erpnext migrate
376
</code></pre>
377
378
h2. stop manually started instance and restart service
379
380
<pre><code class="shell">
381
CTRL-C
382
sudo systemctl start docker-compose-erpnext
383
</code></pre>
384
385
h2. tidy up ..
386
387
<pre><code class="shell">
388
sudo docker system prune
389
</code></pre>
390 4 Jeremias Keihsler
391 19 Jeremias Keihsler
h2. create custom app image (erpnext & eu_einvoice & erpnext_datev)
392 4 Jeremias Keihsler
393 1 Jeremias Keihsler
https://github.com/frappe/frappe_docker/blob/main/docs/custom-apps.md
394 19 Jeremias Keihsler
395 20 Jeremias Keihsler
remove existing image, as rebuiling into the same version seems to cause issues (as of 2025-08-04)
396 19 Jeremias Keihsler
<pre><code class="shell">
397
docker image ls
398
docker image rm ...
399
</code></pre>
400 4 Jeremias Keihsler
401
<pre><code class="shell">
402 8 Jeremias Keihsler
cd ~
403 27 Jeremias Keihsler
/bin/rm -r frappe_docker
404 8 Jeremias Keihsler
git clone https://github.com/frappe/frappe_docker
405
cd frappe_docker
406
407 6 Jeremias Keihsler
docker pull mariadb:10.6
408
docker pull redis:6.2-alpine
409
</code></pre>
410
411
<pre><code class="shell">
412 4 Jeremias Keihsler
export APPS_JSON='[
413
  {
414
    "url": "https://github.com/frappe/erpnext",
415
    "branch": "version-15"
416
  },
417
  {
418 28 Jeremias Keihsler
    "url": "https://github.com/frappe/hrms",
419
    "branch": "version-15"
420
  },
421
  {
422 4 Jeremias Keihsler
    "url": "https://github.com/alyf-de/eu_einvoice.git",
423
    "branch": "version-15"
424 18 Jeremias Keihsler
  },
425 17 Jeremias Keihsler
  {
426
    "url": "https://github.com/alyf-de/erpnext_datev.git",
427
    "branch": "version-15"
428
  }
429 4 Jeremias Keihsler
]'
430
431
export APPS_JSON_BASE64=$(echo ${APPS_JSON} | base64 -w 0)
432
433
echo ${APPS_JSON}
434
echo ${APPS_JSON_BASE64}
435 5 Jeremias Keihsler
</code></pre>
436 4 Jeremias Keihsler
437
<pre><code class="shell">
438
docker build \
439
  --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
440
  --build-arg=FRAPPE_BRANCH=version-15 \
441
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
442 32 Jeremias Keihsler
  --tag=bf_erpnext_e:15.106.0 \
443 4 Jeremias Keihsler
  --file=images/layered/Containerfile .
444 7 Jeremias Keihsler
445 5 Jeremias Keihsler
docker image ls
446 1 Jeremias Keihsler
</code></pre>
447 5 Jeremias Keihsler
448 10 Jeremias Keihsler
<pre><code class="shell">
449 5 Jeremias Keihsler
...
450 32 Jeremias Keihsler
  image: bf_erpnext_e:15.106.0
451 5 Jeremias Keihsler
  pull_policy: never
452 10 Jeremias Keihsler
</code></pre>
453 7 Jeremias Keihsler
454
backend container
455 10 Jeremias Keihsler
<pre><code class="shell">
456 9 Jeremias Keihsler
docker exec -it erpnext-backend-1 bash
457 7 Jeremias Keihsler
bench --site erpnext migrate
458 30 Jeremias Keihsler
bench --site erpnext install-app hrms
459 7 Jeremias Keihsler
bench --site erpnext install-app eu_einvoice
460 21 Jeremias Keihsler
bench --site erpnext install-app erpnext_datev
461 7 Jeremias Keihsler
bench --site erpnext migrate
462 10 Jeremias Keihsler
</code></pre>
463 7 Jeremias Keihsler
464 11 Jeremias Keihsler
* restart
465
* tidy up
466
467
<pre><code class="shell">
468
cd ~
469
/bin/rm -r frappe_docker
470
docker system prune
471
docker image ls
472
docker image rm "unneeded image"
473
</code></pre>