Deploy Docker Apps (Kit and Pro Plan)
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 available only in Tier I servers as they offer the most computing resources we currently offer
When this feature enabled, these things applied:
- assign
/etc/subuid
+/etc/subgid
to allow docker using sub uids for assigning containers. - assign
/var/lib/systemd/linger
to allow backround processes not get killed when SSH session terminates. - registering
dockerd
as user-scoped systemd daemon bydockerd-rootless-setuptool.sh
and set it to run at startup.
Example
The deployment script below activates docker
capabilities and starts a "hello world" container for demo.
# Requires Kit plan or higher!
source: clear
features:
- docker
nginx:
passenger:
enabled: 'on'
app_start_command: 'socat TCP-LISTEN:$PORT,fork TCP:$$RESERVED_IP$$:8080'
commands:
- docker run -d --rm --name webserver -p $$RESERVED_IP$$:8080:80 quay.io/libpod/banner
Let's examine the reason why we use docker run
commands as such:
- Using
docker run
will create and start a new container pulled fromquay.io/libpod/banner
. - We're forwarding to
$$RESERVED_IP$$
with a given port which is a random local IPv4 address127.x.x.x
. --name webserver
denotes the name of this container iswebserver
for easy debugging when inspecting via SSH later.socat
is used as port forwarder from NGINX to$$RESERVED_IP$$:8080
which is what the docker container listen to.
The $$RESERVED_IP$$
is a special constant and you can see the value replaced once the script has been deployed.
Example with Docker Compose
To use docker-compose.yml
, you can to run it via docker compose
.
The example below setup Plausible self-hosting with their database depedencies.
# Requires Kit plan or higher!
source: https://github.com/plausible/hosting
features:
- docker
nginx:
root: public_html/public
passenger:
enabled: 'on'
app_start_command: 'socat TCP-LISTEN:$PORT,fork TCP:$$RESERVED_IP$$:8000'
commands:
- get_hash() { openssl rand -base64 64 | tr -d '\\n'; }
- sed -i 's/8000:8000/$$RESERVED_IP$$:8080:8000/g' docker-compose.yml
- echo BASE_URL=https://$DOMAIN > plausible-conf.env
- echo SECRET_KEY_BASE=\`get_hash\` >> plausible-conf.env
- docker compose up -d
We use the same technique to force docker listen to custom $$RESERVED_IP$$
. Since many projects have variety of docker compose setup, you might have to manually edit your docker-compose.yml
to expose the port that NGINX can listen to.
Healthcheck
While your app and it services runs 24/7, sometimes your app can crash on itself. Make sure your docker containers can heal itself by adding health checks and run an additional autoheal container. Please make sure the container autoheal binds docker.sock with your own rootless docker sock path by running echo $DOCKER_HOST
from terminal.
services:
+ autoheal:
+ restart: always
+ image: willfarrell/autoheal
+ environment:
+ - AUTOHEAL_CONTAINER_LABEL=all
+ volumes:
+ - /run/user/1234/docker.sock:/var/run/docker.sock
plausible_db:
image: postgres:16-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
+ healthcheck:
+ test: pg_isready
plausible:
image: ghcr.io/plausible/community-edition:v2.1.1
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
+ healthcheck:
+ test: wget --no-verbose --tries=1 --spider http://127.0.0.1:8000 || exit 1
depends_on:
plausible_db:
+ condition: service_healthy
ports:
- 127.0.0.1:8000:8000
env_file:
- plausible-conf.env
Then run docker compose up -d
again.
Port Allocation Policy
Many docker compose setup have port exposed to local ports such as 9000
by default. If you leave them unconfigured you'll be surprised that it doesn't work, because we block them for your safety.
If you just want to expose your port for local development, you can change the port to above than 32000 (e.g. 33000
or 34567
). Be careful that anyone also see that exposed port regardless of the domain, which is why we recommend to bind your docker instance to a loopback address and bind them through NGINX.
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 --user
systemctl start docker --user
Custom systemd daemon
You can also create your own System daemon in userspace for your own background service. For instance, you might want to install your own PHP with additional extensions we don't cover.
mkdir -p $HOME/.local/share/systemd/user
cat << EOF > $HOME/.local/share/systemd/user/custom-php.service
[Unit]
Description=FPM
Documentation=Custom PHP FPM
After=network.target
[Service]
Type=simple
WorkingDirectory=$HOME
ExecStart=/opt/remi/php74/root/usr/sbin/php-fpm -c $HOME/etc/php7.4 -y $HOME/etc/php-fpm.conf -F
TimeoutStopSec=5
Restart=always
[Install]
WantedBy=default.target
EOF
cat << EOF > $HOME/etc/php-fpm.conf
error_log = $HOME/logs/php-fpm.log
[wordpress_site]
listen = $HOME/etc/php.sock
listen.owner = $USER
listen.group = $USER
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s
EOF
systemctl enable custom-php --user
systemctl start custom-php --user
Then bind like this:
features:
- php etc/php.sock