Project

General

Profile

Ubuntu OS Setup

Introduction

If your development system is running on Ubuntu, follow the steps in this section. The Docker images themselves have a lot of setup done already, but it is important to setup the OS environment to properly host the Docker containers upon which all the other conversion and runtime processing is built.

On Ubuntu, by default there is a bash shell available. In this step, you will need to install Docker CLI (the Docker Command Line Interface). Do NOT install Docker Desktop.

This section will guide you to installing Docker Engine using the official Docker APT repository. It is intended for command-line usage only (no Docker Desktop) on Ubuntu 24.04 (Noble).

At the end of this setup, you should be able to open a bash shell and run Docker inside it.

Prerequisites

  • Ubuntu system with sudo access (administrative rights).
  • Internet connectivity.
  • No existing Docker packages installed

Install/Setup Docker

The simplest way to install Docker on Ubuntu is:

sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl enable --now docker

This installation method is sufficient for most development use cases.

For environments that require newer Docker features or closer alignment with production systems, you may alternatively install Docker using the official Docker repositories:

https://docs.docker.com/engine/install/ubuntu/

Recommendations

Make sure to uninstall unofficial Docker packages, and do not use Docker Desktop. We have experienced mixed results with Docker Desktop, and the Command Line Interface has been the most operationally consistent method to perform tasks. The Install using the apt repository method would be the best method to use, and is the one Golden Code uses internally for our systems.

Post Installation

Create a docker group and add your user:

 sudo groupadd docker
 sudo usermod -aG docker $USER

If you have other users to add, you can substitute their ID for $USER, and rerun. Be careful with a tool like gpasswd as they completely replace the membership with what you pass in. If you have a lot of users, you can use a loop:

for user in user1 user2 user3 user4 user5; do sudo usermod -aG docker $user; done

Any users added to the group must log out and log back in so their your group membership is re-evaluated. id -nG needs to show the docker group; if this is not visible, logout and login again, or reboot.

You should enable the buildkit feature in the /etc/docker/daemon.json:

{
  "features": {
    "buildkit": true
  }
}

Restart Docker: sudo systemctl restart docker.

Verify Docker installation

From a bash prompt:

docker version
docker info 
docker buildx ls
docker run hello-world

All commands should complete without sudo (after group change). The buildx commands require BuildKit to be enabled.

Space Requirements

Docker does not substantially change the application’s runtime storage requirements. The database, logs, configuration, dump files, diagnostics, integrations, and other persistent application data require approximately the same space as a traditional non-Docker installation.

However, Docker adds an additional storage location for container images, writable container layers, build cache, named volumes, and logs. By default on Ubuntu, this storage is under:

/var/lib/docker

Therefore, systems using Docker must ensure that the filesystem containing /var/lib/docker has enough free space for:
  • Docker images
  • container writable layers
  • Docker build cache
  • named Docker volumes, unless volumes are mounted elsewhere
  • container JSON logs
  • temporary image pull/build activity

If /var is a small separate filesystem, Docker may exhaust that filesystem even when the application data directories have sufficient space.

Area Typical location Notes
Docker images /var/lib/docker Image layers for base, FWD, app, PostgreSQL images
Container writable layers /var/lib/docker Should remain small if persistent data is bind-mounted or stored in named volumes
Docker named volumes /var/lib/docker/volumes Includes DB volume unless explicitly relocated
Application configuration bind-mounted deploy/etc, etc. Same sizing as non-Docker
Application logs bind-mounted deploy/logs Same sizing as non-Docker, depends on retention
PostgreSQL data named volume or bind mount Same sizing as non-Docker DB cluster
DB dumps/import files bind-mounted dump directory Same sizing as non-Docker dump/import workflow
Build cache /var/lib/docker/buildkit Only relevant on systems building images

For production or long-running environments, place persistent application data and PostgreSQL data on explicitly sized storage rather than relying on Docker’s default /var/lib/docker location. If Docker named volumes are used, ensure /var/lib/docker is on a filesystem sized for the database and image storage, or configure Docker’s data-root to point to a larger filesystem.

Alternate Locations

If it is necessary to keep the images in another location, other than on the /var location, the option of modifying the locations is available. Note that containerd is a base function for Docker, and we suggest modifying that at the same time as Docker (if required.)

Variable Controls Built-in default
docker_data_root Docker's data-root — images, container layers, volumes, build cache /var/lib/docker
containerd_data_root containerd's root — its content store and snapshots /var/lib/containerd

For Docker, the built-in value can be overridden by updating /etc/docker/daemon.json with the value data-root (where <path> is where you want the storage located, for example /opt/docker-data/docker):

{
    "data-root": "<path>" 
}

For containerd, update the /etc/containerd/config.toml configuration file's "root" value set to the path, for example /opt/docker-data/containerd:

root = "<path>" 

If the above changes are made, restart the services:

sudo systemctl restart docker
sudo systemctl restart containerd

Note, this does not account for migration of any existing data.

Migrating Existing Data After-the-Fact

WARNING: There is potential data loss here. Always make sure you have a backup, and a restoration plan before embarking upon it.

Use this when a host’s data-root has changed (e.g. a box that ran with /opt/docker-data is being switched back to /var/lib/docker, or vice-versa) and you want to keep the existing images/containers/volumes instead of starting fresh.

Replace OLD and NEW below with the relevant paths, e.g. OLD=/opt/docker-data/docker NEW=/var/lib/docker.

1. Make the appropriate configuration change so daemon.json / config.toml already point at the new location. Docker will have restarted empty at the new path — that is
expected; the steps below backfill the data.

2. Stop the daemons (order matters). Docker runs on top of containerd, so stop Docker first:

sudo systemctl stop docker docker.socket containerd

3. Copy the data, preserving hardlinks/permissions/xattrs. The overlay2 storage driver relies heavily on hardlinks, so rsync -a alone is not enough — you must add -H (and -A -X for ACLs/xattrs), or
images will balloon in size and may break:

# Docker data-root
sudo rsync -aHAX --numeric-ids --info=progress2 /opt/docker-data/docker/ /var/lib/docker/

# containerd root (only if you also moved containerd_data_root)
sudo rsync -aHAX --numeric-ids --info=progress2 /opt/docker-data/containerd/ /var/lib/containerd/

Note the trailing slashes on both sides (copy contents, not the directory itself). Make sure the destination exists first (the playbook creates a custom /opt path with mode 0711; Docker/containerd own /var/lib/...).

4. Start the daemons (reverse order)

sudo systemctl start containerd docker

5. Verify

docker info --format '{{.DockerRootDir}}' # expect the NEW path
sudo containerd config dump | grep -E '^\s*root\s*=' # expect the NEW path
docker images # your images should be present
docker ps -a # your containers should be present

6. Reclaim the old location (only once verified)

sudo rm -rf /opt/docker-data/docker /opt/docker-data/containerd
# adjust to the OLD paths

Some Helpful CLI commands for Storage

docker system df
docker images
docker ps -s
docker volume ls
docker volume inspect <volume_name>
du -sh /var/lib/docker
df -h /var /var/lib/docker

IMPORTANT: UFW vs iptables Warning

Docker manages networking using iptables rules. If you are using UFW (Uncomplicated Firewall), Docker bypasses UFW rules by default. Published container ports may be accessible even if UFW denies them. Docker’s own documentation warns about this behavior: https://docs.docker.com/engine/install/ubuntu/#firewall-limitations


© 2004-2026 Golden Code Development Corporation. ALL RIGHTS RESERVED.