Projekt

Allgemein

Profil

Setup erpnext15 dockerized » Historie » Version 31

Jeremias Keihsler, 15.03.2026 12:41

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