Skip to main content

Deploy Docker Apps (Kit and Pro Plan)

Docker in DOM Cloud is powered by Podman. It's always run in rootless mode and allows running 24/7. Because of how powerful and resouce consuming this is only available with Kit and Pro user plan.

The podman CLI is available as a system-wide packages. docker is simply an alias to podman. A preconfiguration is required by activating podman feature via system runner to:

  • assign /etc/subuid + /etc/subgid to allow podman rootless using sub uids for assigning containers.
  • assign /var/lib/systemd/linger to allow backround processes not get killed when SSH session terminates.

Port Allocation Policy

A docker service should run all the time and have a standby port hidden from the internet.

Remember that DOM Cloud servers is a shared hosting environment, so only expose your port only for public-facing service. A port between 9000 and 32000 is a recommended port number. A port number 32768 and above is not recommended as it's an ephemeral ports only for internal/test usage (firewall don't block incoming traffic for them).

We'll choose this number for you by random for use through the documentation: 16004

Example

The deployment script below activates docker capabilities and starts a "hello world" podman container for demo.

https://github.com/domcloud/recipes/blob/master/docker.yml
source: clear
features:
- docker
nginx:
passenger:
enabled: 'on'
app_start_command: 'socat TCP-LISTEN:$PORT,fork TCP:localhost:16004'
commands:
- docker run -t --name webserver -p 16004:80 quay.io/libpod/banner

Let's examine the reason why we use docker run commands as such:

  • Using run will create and start a new container pulled from quay.io/libpod/banner.
  • We're forwarding from host's port with number 16004 to container's port with number 80. This port number is permanent.
  • The 80 from -p $PORT:80 implies that the app (quay.io/libpod/banner) is listening on port 80 inside the container.
  • --name webserver denotes the name of this container is webserver for easy debugging when inspecting via SSH later.
  • socat is used as port forwarder from $PORT given from passenger phusion to 16004 which your docker

Example with Docker Compose

To use docker-compose.yml, you need to run it via podman-compose. docker compose is not available due to Podman version is still on 4.6.1.

The example below setup Plausible self-hosting with their database depedencies.

https://github.com/domcloud/recipes/blob/master/boot-plausible.yml
# 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:localhost:16004'
commands:
- get_hash() { openssl rand -base64 64 | tr -d '\n'; }
- sed -i 's/8000:8000/16004:8000/g' docker-compose.yml
- echo BASE_URL=https://$DOMAIN > plausible-conf.env
- echo SECRET_KEY_BASE=`get_hash` >> plausible-conf.env
- podman-compose down
- podman-compose up -d

Boot at system startup

While it's infrequent, our server may restart during scaling and other reasons. So future-proof your docker instance using systemd. That will make your docker app run at boot.

commands:
- mkdir -p ~/.config/systemd/user
- filename: app.service
content: |
[Unit]
Description=App Daemon
After=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/public_html
ExecStart=/usr/bin/env podman-compose up -d
ExecReload=/usr/bin/env podman-compose down
Restart=always

[Install]
WantedBy=default.target
- mv app.service ~/.config/systemd/user/app.service
- systemctl --user daemon-reload
- systemctl --user start app
- systemctl --user enable app

After this have been implemented you can also start, restart and stop your docker app using systemctl --user start app, systemctl --user restart app and systemctl --user stop app respectively.

Differences

Using docker has benefit compared other deployment system. These includes:

Allow additional background services

Adding entries to /var/lib/systemd/linger will make sure that your processes won't get killed anytime you log out from SSH session. This also means you can add custom database system (like MongoDB and Redis) simply by pulling and starting the database service with detached mode (or using docker's compose).

Note that with this benefit limitations by Fair Usage still implies. We won't restrict your CPU and RAM limits but still watching overall system performance and deliberately kills it if it proven to abuse our resources. Additionally, there should be no public port exposed to the host other than what's given from passenger's $PORT to avoid depleting server's ports allocations.

Allow building apps by Continous Integration (CI)

While other deployment system is benefited by simpler DX (you can code and fix bugs directly in production) and incremental builds, there are often a reasonable choices to use CI to build apps and only deliver the binary to us via docker images.

One of the benefit is you will be able to version your binaries via CI artifacts, this including releasing binaries via code versioning. This also added more security by not exposing your valuable source code to us, and lesser computation and storage used for compiling binaries by delegating it to CI instead of from our server.

... (example deployment code)

Advanced logging and microservice managements

Here are some additional reasons to use docker:

  • Use docker compose to configure your apps along with its service depedencies
  • Use docker ps to inspect running containers, Use docker logs to inspect logs
  • Allow limiting CPU and RAM resources
  • And many more...