Docker Install
InterDiode provides Docker/OCI images that are available in its Docker repository. It is possible to always use the latest stable tag or to use another service that handles updating Docker images.
This guide explains the setup based on docker-compose, but the installation of docker-compose itself is out of scope of this documentation. To do this, please follow the official install instructions.
If you want to use the built-in air gap protocol using UDP packets, you are responsible to inject the MAC address in the ARP cache of the host machine, before using the integrated air gap protocol. This must be done on the host machine, not in the Docker container.
Docker-compose File
Here are the Docker-compose files for the black (connected to the internet) and red (on your internal network) instances. InterDiode is configured by environment variables, and the complete list of available environment variables is available in the configuration. A single worker is used in these examples, but you should spawn multiple workers for better performance and reliability in production, and dedicated some of them to several types of tasks. Please refer to the documentation on processes for more details on how to configure the server and the workers.
Multiple instances of workers can be spawned if required.
By default, two volumes should be mounted to the containers:
/data/files, which is the main storage for InterDiode, and must be shared between all processes,/data/caches, as a shared caches between all processes.
services:
background_black:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 background
depends_on:
db_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
deploy:
resources:
limits:
memory: 6G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-background.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/black:/data/files
- ./caches/black:/data/caches
beat_black:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 beat
depends_on:
db_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-beat.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/black:/data/files
- ./caches/black:/data/caches
db_black:
healthcheck:
interval: 1s
retries: 10
test: [CMD, pg_isready, -U, interdiode, -d, interdiode_db]
timeout: 1s
image: postgres:18
restart: always
volumes:
- ./postgres/black:/var/lib/postgresql/data/postgresql
migrate_black:
command: interdiode-ctl configuration apply --no-input
depends_on:
db_black:
condition: service_healthy
redis_black:
condition: service_healthy
env_file:
- ./compose.env
image: interdiode/interdiode:2026.6.13
volumes:
- ./files/black:/data/files
- ./caches/black:/data/caches
nginx_black:
command: nginx -g 'daemon off;'
healthcheck:
interval: 1s
retries: 10
test: [CMD, curl, -f, 'http://localhost/health']
timeout: 1s
image: nginx:latest
ports:
- 127.0.0.1:8881:80
restart: always
volumes:
- ./compose/nginx_black.conf:/etc/nginx/nginx.conf:ro
redis_black:
command: redis-server --requirepass 'my-redis-password' --save 60 1 --loglevel warning
healthcheck:
interval: 1s
retries: 10
test: [CMD, redis-cli, ping]
timeout: 1s
image: redis:alpine
restart: always
send_black:
command: interdiode-ctl hairgap --prometheus-bind 0.0.0.0 --prometheus-port 9000 send
depends_on:
db_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-hairgap.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/black:/data/files
- ./caches/black:/data/caches
web_black:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 http
depends_on:
db_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
nginx_black:
condition: service_healthy
redis_black:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-http.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
ports:
- 8081:8081
restart: always
volumes:
- ./files/black:/data/files
- ./caches/black:/data/caches
services:
background_red:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 background
depends_on:
db_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
deploy:
resources:
limits:
memory: 6G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-background.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/red:/data/files
- ./caches/red:/data/caches
beat_red:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 beat
depends_on:
db_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-beat.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/red:/data/files
- ./caches/red:/data/caches
db_red:
healthcheck:
interval: 1s
retries: 10
test: [CMD, pg_isready, -U, interdiode, -d, interdiode_db]
timeout: 1s
image: postgres:18
restart: always
volumes:
- ./postgres/red:/var/lib/postgresql/data/postgresql
migrate_red:
command: interdiode-ctl configuration apply --no-input
depends_on:
db_red:
condition: service_healthy
redis_red:
condition: service_healthy
env_file:
- ./compose.env
image: interdiode/interdiode:2026.6.13
volumes:
- ./files/red:/data/files
- ./caches/red:/data/caches
nginx_red:
command: nginx -g 'daemon off;'
healthcheck:
interval: 1s
retries: 10
test: [CMD, curl, -f, 'http://localhost/health']
timeout: 1s
image: nginx:latest
ports:
- 127.0.0.1:8882:80
restart: always
volumes:
- ./compose/nginx_red.conf:/etc/nginx/nginx.conf:ro
receive_red:
command: interdiode-ctl hairgap --prometheus-bind 0.0.0.0 --prometheus-port 9000 receive
depends_on:
db_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-hairgap.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
restart: always
volumes:
- ./files/red:/data/files
- ./caches/red:/data/caches
redis_black:
command: redis-server --requirepass 'my-redis-password' --save 60 1 --loglevel warning
healthcheck:
interval: 1s
retries: 10
test: [CMD, redis-cli, ping]
timeout: 1s
image: redis:alpine
restart: always
redis_red:
command: redis-server --requirepass 'my-redis-password' --save 60 1 --loglevel warning
healthcheck:
interval: 1s
retries: 10
test: [CMD, redis-cli, ping]
timeout: 1s
image: redis:alpine
restart: always
web_red:
command: interdiode-ctl run --prometheus-bind 0.0.0.0 --prometheus-port 9000 http
depends_on:
db_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
nginx_red:
condition: service_healthy
redis_red:
condition: service_healthy
deploy:
resources:
limits:
memory: 2G
env_file:
- ./compose.env
healthcheck:
interval: 1s
retries: 10
test: [CMD, python, -c, 'import os; fd = open(''/data/run/interdiode-http.pid''); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()']
timeout: 1s
image: interdiode/interdiode:2026.6.13
ports:
- 8082:8082
restart: always
volumes:
- ./files/red:/data/files
- ./caches/red:/data/caches