Installing Docker CE on CentOS 7
I held out against Docker on servers for a long time. Then I kept needing a Redis for one app, a GitLab runner, or one specific version of some tool a developer wanted, and installing all that into the host got old fast. CentOS 7 is a fine host as long as you use Docker's own repository, not the docker package from CentOS extras, which is an older fork that behaves differently.
This installs Docker CE stable (the 18.09 branch right now) and docker-compose, sets up the daemon for server use, and covers the CentOS storage and firewall traps. I assume CentOS 7.4+ fully updated, and an XFS root created with ftype=1 (the default) or a separate disk for /var/lib/docker. Check with xfs_info / | grep ftype.
Repository
sudo yum remove -y docker docker-common docker-client docker-engine
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
This writes /etc/yum.repos.d/docker-ce.repo with the docker-ce-stable repository enabled and the edge/test channels disabled.
Install
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable docker
sudo systemctl start docker
docker version
To pin a version instead of taking the latest (I do, on anything important), list what's available and install by version string:
yum list docker-ce --showduplicates | sort -r
sudo yum install -y docker-ce-18.09.3 docker-ce-cli-18.09.3 containerd.io
Running docker without root
Members of the docker group can talk to the daemon socket. That's equivalent to root on the host, so I only add people who already have sudo:
sudo usermod -aG docker deploy
Log out and back in for the group to take effect.
Daemon config
The defaults are aimed at developers. On a server I write /etc/docker/daemon.json before running anything important, since changing the storage driver later means losing existing images:
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
},
"live-restore": true
}
overlay2 is the right driver on CentOS 7.4+ with XFS ftype=1. Without ftype=1 Docker refuses it, and I'd fix the filesystem rather than fall back to devicemapper. log-opts stops a chatty container filling the disk with /var/lib/docker/containers/*/*-json.log; I learned that from a full disk. live-restore keeps containers running across a daemon restart or upgrade.
sudo systemctl restart docker
docker info | grep -E 'Storage Driver|Logging Driver|Live Restore'
docker-compose
Compose is a separate binary, not in the yum repo. Download the release and make it executable:
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
firewalld surprises
Docker inserts its own iptables rules for published ports, bypassing firewalld's zones. A container started with -p 6379:6379 is reachable from the Internet even if firewalld would block 6379. That one is nasty. If only the host needs the port, bind it to localhost:
docker run -d --name redis -p 127.0.0.1:6379:6379 redis:5
If you need containers to reach each other and the host across the docker0 bridge on a firewalld host, add the interface to the trusted zone:
sudo firewall-cmd --permanent --zone=trusted --add-interface=docker0
sudo firewall-cmd --reload
Also note that restarting firewalld flushes Docker's rules; restart docker afterwards (systemctl restart docker) to recreate them.
Smoke test
docker run --rm hello-world
docker run -d --name web -p 127.0.0.1:8080:80 nginx:1.15
curl -I http://127.0.0.1:8080/
docker ps
docker rm -f web
hello-world confirms the daemon can pull and run; the nginx test confirms port publishing and that the overlay2 driver serves a real image. docker info should show no warnings at the bottom.
Errors I've hit
Error starting daemon: error initializing graphdriver: overlay2: the backing xfs filesystem is formatted without d_type support: filesystem made withftype=0. Mount a new volume formatted withmkfs.xfs -n ftype=1at/var/lib/docker.Got permission denied while trying to connect to the Docker daemon socket: user isn't in thedockergroup, or hasn't logged out since being added.docker: Error response from daemon: driver failed programming external connectivity ... iptables failed: firewalld restarted after docker.systemctl restart docker.- Containers can't resolve DNS but the host can: the host's
/etc/resolv.confpoints at127.0.0.1. Set"dns": ["192.168.10.5", "8.8.8.8"]indaemon.json. yum install docker-cefails withRequires: container-selinux >= 2.9: enable theextrasrepository, where CentOS ships that package.
I keep each app in /srv/docker/<app>/docker-compose.yml with restart: unless-stopped, and the host stays updated, firewalled, and SELinux-enforcing like any other.