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
sudoaccess (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
/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.