Deploy Docker Apps
Docker allows you to run any arbitrary apps in a simple docker compose file. Docker in DOM Cloud is powered by Docker rootless mode. Enabling docker features is implicitly allows running 24/7 (doesn't have to actually using docker). Because of how powerful and resouce consuming this is only available starting with Kit Plan.
Docker is also available only in some servers as they offer the most computing resources we currently offer.
When this feature enabled, these things applied:
- assign
/etc/subuid+/etc/subgidto allow docker using sub uids for assigning containers. - assign
/var/lib/systemd/lingerto allow backround processes not get killed when SSH session terminates. - registering
dockerdas user-scoped systemd daemon bydockerd-rootless-setuptool.shand set it to run at startup.
Because Docker run as daemon, the feature also allows any app under the site have a long running processes i.e. the 3 hour process limit is automatically appealed no matter if it actually uses Docker or not.
Enable docker with writing this to the deployment script:
features:
- docker
Getting Started
The deployment script below activates docker capabilities and set up a docker-compose.yml file from services script.
# Requires Kit plan or higher!
source: clear
features:
- docker
services:
hello_world:
# https://github.com/cernoel/docker-hello-world
image: cernoel/hello-world:main
restart: always
ports:
- 8080:8000
The services subpath is equal to services declared in docker compose file. In fact, you can simply copy paste any docker compose file from internet to our deployment script! The port mapping will be linked automatically to our NGINX system. After deployment, you can examine the final docker-compose.yml in the ~/public_html:
services:
hello_world:
image: cernoel/hello-world:main
restart: always
ports:
- 12345:8000/tcp
The host port has been changed to ensure it's only assigned to your website. The port range chosen is between 10000 to 30000, which is a port range that blocked from outside. If you already set the port range >32000 the port chosen will be left unchanged to allow you expose that to the greater internet.
When calling services in deployment system, docker compose down and docker compose up will be automatically everytime a deployment script is called with services: prop. Note that you cannot declare volumes: and networks: using deployment script. See With Existing Docker Compose for solution.
How does it know if port 8080 is the web gateway? Because we're guessing. To enforce which port forwarded by NGINX, use
With Existing Docker Compose
What if you already have docker-compose.yml file, perhaps from a GitHub repo?
The example below setup Plausible self-hosting with their depedencies.
source: https://github.com/plausible/hosting
features: docker
services: docker-compose.yml # docker compose always ran after commands
commands:
- echo BASE_URL=https://$DOMAIN > plausible-conf.env
- echo SECRET_KEY_BASE=$(openssl rand -base64 48) >> plausible-conf.env
- echo TOTP_VAULT_KEY=$(openssl rand -base64 32) >> plausible-conf.env
You can configure your containers using docker commands in SSH. To reconfigure composer file cleanly just like running services: via deployment script without leaving SSH you can run:
docker compose -f ~/public_html/docker-compose.yml down --remove-orphans
docker compose -f ~/public_html/docker-compose.yml up --build --detach
Healthcheck
While your app and it services runs 24/7, sometimes your app can crash on itself. Use proxfix NOHUP mode to watch docker on every request.
nginx:
root: public_html/public
passenger:
enabled: on
app_start_command: proxfix docker compose up --force-recreate -d
env_var_list:
- NOHUP=1
- TARGET=127.0.0.0:8080
The proxfix process spawns and check if TARGET=127.0.0.0:8080 still running. If it not, it will spawn docker compose up --force-recreate -d and forwarding requests to TARGET address, which is should be where docker listening to. To know the correct TARGET value, check to your docker-compose.yml file.
Connecting with Host Services
If you want to use host services such as our MariaDB / PostgreSQL / Valkey database, you can use 10.0.2.2 as the IP for connecting host inside container. Do not use host.docker.internal as it's not working for rootless Docker.
Using our shared database has a benefit of faster disk speed and be included to our daily backup.
Playing Docker with SSH
You can also play with Docker directly using SSH with docker run -ti --rm ubuntu /bin/bash. It will create a root Ubuntu shell that you can play with. To make your changes persistent, please consider writing a Dockerfile or explore existing container images with Docker Hub.
Managing containers
All docker commands is available as usual. To make managing a bit easier, DOM Cloud also installed lazydocker, a TUI for managing docker available via SSH.

Managing systemd daemon
Your docker instance is registered as user-scoped systemd service. You can call these systemd commands to diagnose docker problems
systemctl status docker --usersystemctl start docker --user
You can also install or uninstall docker engine via SSH by running below.
dockerd-rootless-setuptool.sh install --skip-iptablesdockerd-rootless-setuptool.sh uninstall --skip-iptables
Troubleshooting
502 Bad Gateway
This could means your docker container is unable to run. Please check docker ps, docker logs, systemctl status docker --user.
If it running normally, please check if NGINX and docker compose running the same proxy_pass. Try deploying service: docker-compose.yml again.
If the docker stopped in SystemD, try enable it systemctl start docker --user, or try run dockerd-rootless.sh in SSH to see if any problem related to the daemon.
exec format error in docker logs
This means the container is not available in system architecture. Our servers can be an arm64 (ARM) not amd64 (Intel), not every image containers have this platform arch. Check it with Docker Hub.
If you confirm that the image containers is amd64 only, please move the server to x64 variant, that's SGA/WDC server -- or build your own image.
Network Slow / Not Working
We use pasta driver for rootless networking which is fast for incoming connections to the container but not for outgoing networks. If you experience frequent network errors during docker build please add --network=host to the docker build args or below for compose file:
services:
app:
build:
context: .
network: host
Diagnose network by running dockerd-rootless-setuptool.sh nsenter. This will put you into a shell environment inside RootlessKit namespace.
Can't Choose Host IP to forward
If you set port forwarding such as 127.1.2.3:8080:80 it won't work since the pasta driver listens to 0.0.0.0:<port> on the host system. It listen to all addresses so it doesn't require NAT / packet translation. Basically that request would go from 127.1.2.3:8080 in the host then 127.1.2.3:80 in the container.
If you have a burning desire to do IP forwarding, you can switch to docker's default slirp4netns by removing envars in systemctl edit docker --user. Please consult to Official docker documentation for more information