手动安装 docker 并配置 sytemctl 管理

一、 下载 docker 二进制文件

根据自己环境选择合适的版本:
https://download.docker.com/linux/static/stable/x86_64/

二、 解压到 /usr/local/docker

创建docker用户及组

groupadd docker
useradd -g docker docker

tar -xzvf docker-19.03.1.tgz
mv docker /usr/local/

三、 使用 systemctl 管理 docker 服务

文件引用自:
https://github.com/moby/moby/blob/master/contrib/init/systemd/docker.service

docker.service

# vim /usr/local/docker/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service
Wants=network-online.target
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/local/docker/dockerd
# ExecStart=/usr/local/docker/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ## 注意这种配置的写法,区别在后面会介绍
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always

# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3

# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity

# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes

# kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target

docker.socket

# vim /usr/local/docker/docker.socket
[Unit]
Description=Docker Socket for the API

[Socket]
# If /var/run is not implemented as a symlink to /run, you may need to
# specify ListenStream=/var/run/docker.sock instead.
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target

3.1 配置 containerd 及相关环境

ln -s /usr/local/docker/containerd /usr/bin/
ln -s /usr/local/docker/dockerd /usr/bin/
ln -s /usr/local/docker/docker-init /usr/bin/
ln -s /usr/local/docker/docker-proxy /usr/bin/
ln -s /usr/local/docker/runc /usr/bin/

3.2 重载 systemd

systemctl daemon-reload

3.3 确保 network-online.target 和 firewalld.service 正常

systemctl status network-online.target
systemctl status firewalld.service

3.4 systemctl 配置 docker 并设置自启

systemctl enable docker.socket --now
systemctl enable docker.service --now

3.5 方便后续操作将 docker 等软连接到 PATH

ln -s /usr/local/docker/docker /usr/bin/
ln -s /usr/local/docker/dockerd /usr/bin/

四、 相关问题

4.1 为什么是 /usr/local/docker

答: 如果按照标准的FHS规范应该是/usr/bin等其他目录,选择/usr/local/docker目录的原因方便后续的升级。

4.2 为什么要软连接containerd到/usr/bin

答:

4.3 两种不同的 ExecStart 写法的区别

第一种: ExecStart=/usr/local/docker/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

  1. -H fd
    这个参数告诉 Docker 守护进程使用文件描述符 (fd) 监听 Docker 客户端的连接。
    这通常用于与 Docker 代理一起使用,以便在代理与 Docker 守护进程之间建立通信。
  2. --containerd=/run/containerd/containerd.sock
    这个参数指定 Docker 守护进程应该使用的 containerd 服务的 Unix 套接字。
    Containerd 是一个用于管理容器的基础设施组件,Docker 守护进程通常会与它一起工作。

第二种: ExecStart=/usr/local/docker/dockerd
未指定参数意味着 Docker 守护进程将使用默认配置来运行,通常会监听 Unix 套接字 /var/run/docker.sock 来接收 Docker 客户端的请求。
即我们在 docker.socket 里配置的路径ListenStream=/var/run/docker.sock

注意: 如果需要使用ExecStart=/usr/local/docker/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
需要将containerd注册成系统服务
并且在 AfterWants 需要引用 containerd.service

4.4 systemctl 另外一种管理 docker 的配置写法

请注意这种写法需要将 containerd 注册成系统服务

docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service containerd.service time-set.target
Wants=network-online.target containerd.service
Requires=docker.socket

[Service]
Type=notify
WorkingDirectory=/usr/local/docker/
ExecStart=/usr/local/docker/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target

docker.socket

[Unit]
Description=Docker Socket for the API

[Socket]
# If /var/run is not implemented as a symlink to /run, you may need to
# specify ListenStream=/var/run/docker.sock instead.
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target