专栏首页蓝天Docker入门之安装Docker

Docker入门之安装Docker

1. 前言

本文操作基于CentOS7,其它Linux发行版本可能存在差异,分基于yum的在线安装和基于二进制包的离线安装(实际还有基于rpm包的离线安装),离线安装可以更多地了解Docker及相关体系。

Docker要求Linux内核版本不低于3.10,并且必须为64位系统,执行命令“docker version”可查看Docker版本。

CentOS7防火墙默认采用的是firewalld管理netfilter子系统,底层调用的仍然是iptables命令,firewalld实际是iptables的一个封装。不同的防火墙相互间存在冲突,使用某其中一个时应禁用其他的。

谨记:容器运行在Linux内核之上,不包含位于内核之上的glibc等库,以及ls等命令。如果容器中的程序依赖glibc等库或者依赖ls等命令,则容器自身应当包含这些设施。另外,容器中的程序等必须和内核兼容,否则将会遇到“FATAL: kernel too old”错误,该错误和库文件ld-linux.so有关。

2. 基本概念

2.1. 仓库

Docker仓库(Repository)是存储Docker镜像的地方。

2.2. 镜像ID和容器ID

镜像(image)是静态的,容器(container)是运行中的镜像。如果说镜像是程序文件,则容器是进程。把镜像ID看作文件名,则容器ID可视为进程ID,因此每次启动的容器ID是不相同的。

同一镜像可以启动多个容器,容器间的ID不会相同:

# docker ps CONTAINER ID IMAGE     COMMAND     CREATED       STATUS       PORTS  NAMES 7518f632b6d0 centos  "/bin/bash" 4 seconds ago Up 2 seconds        focused_turing d97bd379589c centos  "/bin/bash" 6 minutes ago Up 6 minutes        friendly_nightingale

3. 创建网桥

容器默认使用网桥网络模式,且默认桥接器名为docker0。在启动Docker之前(即执行命令“sytemctl start docker.service”前),需要先创建和启用好网桥,执行下例命令可创建和设置网桥。

# ip link add name docker0 type bridge # 创建网桥 # ip addr add dev docker0 172.17.0.1/16 # 设置网桥的IP和网关 # ip link set docker0 up # 启用网桥 # ip a # 查看创建好的网桥 1: lo: mtu 65536 qdisc noqueue state UNKNOWN     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00     inet 127.0.0.1/8 scope host lo        valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc noop state DOWN qlen 1000     link/ether 60:eb:69:fe:2e:20 brd ff:ff:ff:ff:ff:ff 3: eth1: mtu 1500 qdisc mq state UP qlen 1000     link/ether 60:eb:69:fe:2e:21 brd ff:ff:ff:ff:ff:ff     inet 10.22.25.101/26 brd 10.223.25.127 scope global eth1        valid_lft forever preferred_lft forever 4: docker0: mtu 1500 qdisc noqueue state UNKNOWN     link/ether 6e:3c:cb:3e:a7:44 brd ff:ff:ff:ff:ff:ff     inet 172.17.0.1/16 scope global docker0        valid_lft forever preferred_lft forever

网桥状态为up,则表示没有起来。如果没有网桥或网桥没有起来,执行“systemctl start docker.service”启动Docker时将可能遇到错误“list bridge addresses failed”而启动失败。

4. 安装Docker

在能访问网络的环境或者有本地Docker仓库的环境,建议使用yum安装,简单省事。

在不能访问网络环境,可手工安装Docker。进入https://download.docker.com/,下载对应的安装包,这里又分两种:一是下载通用的二进制安装包,二是下载RPM安装包。相对yum安装,手工安装(离线安装)可以了解更多细节,有助于深入了解Docker。

4.1. 二进制安装

这个方法比较复杂,容易遇到各种问题。

4.1.1. 下载安装

通用的二进制安装包下载路径:https://download.docker.com/linux/static/stable/x86_64/,截至2019/12/17可下载的最新版本为docker-19.03.5.tgz,就以它为安装对象。下载好后,将docker-19.03.5.tgz上传到目标Linux的任一目录,然后进入该目录解压docker-19.03.5.tgz,解压后的内容如下:

# ls /usr/bin/docker containerd  containerd-shim  ctr  docker  dockerd  docker-init  docker-proxy  runc

解压生成的目录Docker下全是64位可执行程序文件,其中dockerd是运行在母机上的服务,dockerd负责加载镜像(image)拉起容器container。

# ls -l /usr/bin/docker 总用量 204720 -rwxr-xr-x 1 root root 34625816 2019-11-13 15:30 containerd -rwxr-xr-x 1 root root  6116160 2019-11-13 15:30 containerd-shim -rwxr-xr-x 1 root root 18850136 2019-11-13 15:30 ctr -rwxr-xr-x 1 root root 65641786 2019-11-13 15:30 docker -rwxr-xr-x 1 root root 72090824 2019-11-13 15:30 dockerd -rwxr-xr-x 1 root root   764144 2019-11-13 15:30 docker-init -rwxr-xr-x 1 root root  2877369 2019-11-13 15:30 docker-proxy -rwxr-xr-x 1 root root  8649792 2019-11-13 15:30 runc

将目录“/usr/bin/docker”加入到环境变量PATH中,如果不这么做,则可将目录/usr/bin/docker下的所有文件复制到目录“/usr/bin”。

4.1.2. 配置服务

新建和编辑文件docker.service,文件docker.service所在目录可有多种选择,实际为systemd查找目录,执行命令“man 5 systemd.unit”或“man 5 systemd.service”可看到所支持的目录包含如下一些:

目录

说明

/etc/systemd/system

Local configuration

/run/systemd/system

Runtime units

/usr/lib/systemd/system

Units of installed packages yum方式安装时,docker.service可能在此目录

以“/etc/systemd/system/docker.service”为例:

# cat /etc/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.com After=network.target rhel-push-plugin.socket Wants=docker-storage-setup.service   [Service] Type=notify NotifyAccess=all EnvironmentFile=-/etc/sysconfig/docker EnvironmentFile=-/etc/sysconfig/docker-storage EnvironmentFile=-/etc/sysconfig/docker-network Environment=GOTRACEBACK=crash ExecStart=/usr/bin/dockerd daemon \           --graph /data/docker \           --exec-opt native.cgroupdriver=systemd \           $OPTIONS \           $DOCKER_STORAGE_OPTIONS \           $DOCKER_NETWORK_OPTIONS \           $ADD_REGISTRY \           $BLOCK_REGISTRY \           $INSECURE_REGISTRY LimitNOFILE=1048576 LimitNPROC=1048576 LimitCORE=infinity TimeoutStartSec=0 MountFlags=slave Restart=on-abnormal   [Install] WantedBy=multi-user.target

其中“--graph”用于指定镜像(image)存放目录。

4.1.3. 启动服务

执行命令“systemctl start docker.service”启动Docker:

# systemctl start docker.service # ps aux|grep docker | grep -v grep root     16052  0.3  0.1 600076 37332 ?        Ssl  16:46   0:00 /usr/bin/docker/dockerd --data-root /data/docker --exec-opt native.cgroupdriver=systemd root     16060  0.1  0.0 571644 22196 ?        Ssl  16:46   0:00 containerd --config /var/run/docker/containerd/containerd.toml --log-level info

4.2. rpm安装

https://download.docker.com/linux/centos/7/x86_64/stable/Packages/下载RPM安装包,以下载docker-ce-19.03.5-3.el7.x86_64.rpm、docker-ce-cli-19.03.5-3.el7.x86_64.rpm、containerd.io-1.2.6-3.3.el7.x86_64.rpm、docker-ce-selinux-17.03.3.ce-1.el7.noarch.rpm为例,其中docker-ce-19.03.5-3.el7.x86_64.rpm依赖其它几个RPM包,而containerd.io-1.2.6-3.3.el7.x86_64.rpm又依赖docker-ce-selinux

基于RPM包安装涉及很多依赖,安装可能复杂(视实际的依赖程度),所以尽量避免这种安装方式。本文尝试时,因为太多的依赖需要安装或更新,导致未能完成。

4.3. yum安装

yum会将Docker安装到/usr/bin目录,可执行“ls /usr/bin/dock*”查看有哪些文件,不同版本会有差异。

实际上可以用yum安装RPM包,但和直接使用RPM命令一样,有复杂的依赖问题,所以除非不得已,最好不要采用yum+RPM包方式安装。这节介绍可访问网络(能访问Docker仓库)时的yum安装。

需要安装的内容包括:

包名

说明

docker-ce

社区版(Community)容器引擎(Docker Engine),依赖containerd.io。包含了: /usr/bin/dockerd /usr/bin/docker-init /usr/bin/docker-proxy

docker-ce-cli

docker-ce的命令行客户端工具,包含了命令行客户端工具/usr/bin/docker

containerd.io

隔离了Docker和OS(比如Linux容器LXC),有独立的官网:https://containerd.io/。

docker

对社区版而言,就是docker-ce,有些非官方仓库需要使用这个名字安装,使用docker-ce报“No package docker-ce available”。

其中docker-ce为容器引擎,安装步骤:

4.3.1. 添加Docker仓库

这一步不一定是必须的,比如内网已配置好本地仓库而不需要访问Docker官方仓库,或者已添加好Docker官方仓库。

如果yum-config-manager不可用,则需执行“yum install -y yum-utils”先安装好yum-config-manager。

执行下列命令添加Docker仓库:

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

完成后,可以目录/etc/yum.repos.d下看到文件docker-ce.repo。如果执行失败,则文件docker-ce.repo为空文件。

4.3.2. 安装docker-ce

执行下列命令安装:

# yum -y install docker-ce

上述实际相当于:

# yum -y install docker.io/docker-ce

如果报“No package docker-ce available”,可改成下列试试:

# yum -y install docker

安装成功后,会产生新文件:

# file /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.service: cannot open (No such file or directory) # ls /usr/bin/dock*                           ls: cannot access /usr/bin/dock*: No such file or directory   # yum -y install docker-ce   # file /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.service: ASCII text # ls /usr/bin/dock*                           /usr/bin/docker  /usr/bin/docker-fetch  /usr/bin/dockertarsum

其中docker.service供systemd使用,当执行“systemctl start docker.service”时依赖文件docker.service定义的信息。文件docker.service不一定要位于目录/usr/lib/systemd/system/,systemd支持搜索多个目录查找docker.service,比如二进制安装时将docker.service放在目录/etc/systemd/system。

默认的文件docker.service内容如下:

# cat /usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.com After=network.target   [Service] Type=notify EnvironmentFile=-/etc/sysconfig/docker EnvironmentFile=-/etc/sysconfig/docker-storage EnvironmentFile=-/etc/sysconfig/docker-network ExecStart=/usr/bin/docker -d $OPTIONS \           $DOCKER_STORAGE_OPTIONS \           $DOCKER_NETWORK_OPTIONS \           $ADD_REGISTRY \           $BLOCK_REGISTRY \           $INSECURE_REGISTRY LimitNOFILE=1048576 LimitNPROC=1048576 LimitCORE=infinity MountFlags=slave TimeoutSec=0   [Install] WantedBy=multi-user.target

其中参数“-d”表示以后台守护进程方式启动,配置项“WantedBy”用于指定随系统启动时docker.service发布的子目录为“multi-user.target”。注意“multi-user.target”的名不能随便取,这是systemd约定的名之一,对应系统启动级别3,可通过命令“systemctl set-default”修改默认级别,multi-user.target的完整目录路径为/etc/systemd/system/multi-user.target。

官方最新的docker.service如下:

# cat /usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com BindsTo=containerd.service After=network-online.target firewalld.service containerd.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/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=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. LimitNOFILE=infinity 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   [Install] WantedBy=multi-user.target

4.3.3. 启动服务

执行命令“systemctl start docker.service”启动Docker:

# systemctl start docker.service # ps aux|grep docker | grep -v grep /usr/bin/docker -d --selinux-enabled -b=none

5. Docker基本操作

5.1. 查看帮助

Docker的各程序或命令基本都支持“--help”参数查看帮助,比如:docker --help、dockerd --help、docker images --help。

5.2. 启动Docker服务

和其它服务一样启动即可,停止和重启方法也相同。

# systemctl start docker.service

5.3. 查看有哪些镜像

执行命令“docker images”,可查看有哪些镜像(image):

# docker images REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE docker.io/hello-world   latest              fce289e99eb9        11 months ago       1.84 kB

如果Docker服务没有起来,执行“docker images”将报如下错误:

# docker images Cannot connect to the Docker daemon. Is the docker daemon running on this host?

5.4. 从仓库拉取镜像

默认拉取到的是latest镜像(image)。

# docker pull hello-world Using default tag: latest Trying to pull repository docker.io/library/hello-world ... latest: Pulling from docker.io/library/hello-world   1b930d010525: Pull complete

如果执行命令“docker images”看不到拉取的镜像(image),则可重拉取后再看看。如果从非Docker官方(docker.io)拉取image,则需要指定仓库地址:

# docker pull myrep.io/public/hello-world

如不确定hello-world所在路径,则可先执行“docker search myrep.io/hello”查找:

# docker search myrep.io/hello-world

如果没有latest版镜像,则可指定版本:

# docker pull myrep.io/public/hello-world:v1

从从Docker官方拉取centos7为例(其中7实为镜像的tag):

# docker pull centos:7

拉取tag为“centos7.2.1511”的镜像:

# docker pull centos:centos7.2.1511

注意,这里并不是“docker pull http://myrep.io/public/hello-world”,没有“http://”或“https://”前缀,否则报错“is not a valid repository/tag: invalid reference format”。

拉取下来的images存放在哪?请参见《指定Docker的images存放目录》一节的内容。官方的“hello-world”镜像长这样子:

# cat /data/docker/image/aufs/imagedb/content/sha256/fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e {"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/hello"],"ArgsEscaped":true,"Image":"sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"8e2caa5a514bb6d8b4f2a2553e9067498d261a0fd83a96aeaaf303943dff6ff9","container_config":{"Hostname":"8e2caa5a514b","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/hello\"]"],"ArgsEscaped":true,"Image":"sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2019-01-01T01:29:27.650294696Z","docker_version":"18.06.1-ce","history":[{"created":"2019-01-01T01:29:27.416803627Z","created_by":"/bin/sh -c #(nop) COPY file:f77490f70ce51da25bd21bfc30cb5e1a24b2b65eb37d4af0c327ddc24f0986a6 in / "},{"created":"2019-01-01T01:29:27.650294696Z","created_by":"/bin/sh -c #(nop)  CMD [\"/hello\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3"]}}

5.5. 运行(启动)容器

以“hello-world”为例(如果不带参数“--rm”运行,则窗口退出后不会自动删除):

# docker run --rm hello-world   Hello from Docker! This message shows that your installation appears to be working correctly.   To generate this message, Docker took the following steps:  1. The Docker client contacted the Docker daemon.  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.     (amd64)  3. The Docker daemon created a new container from that image which runs the     executable that produces the output you are currently reading.  4. The Docker daemon streamed that output to the Docker client, which sent it     to your terminal.   To try something more ambitious, you can run an Ubuntu container with:  $ docker run -it ubuntu bash   Share images, automate workflows, and more with a free Docker ID:  https://hub.docker.com/   For more examples and ideas, visit:  https://docs.docker.com/get-started/

可为“docker run”指定资源控制参数,比如限定内存等。执行“docker run --help”可以看到相关参数说明。

5.6. 查看指定的镜像

# docker inspect hello-world [     {         "Id": "sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e",         "RepoTags": [             "docker.io/hello-world:latest"         ], 。。。 。。。

5.7. 修改镜像存放目录

这根Docker版本有关,有些版本的叫/usr/bin/dockerd,有些叫/usr/bin/docker,有些叫/usr/bin/docker-current,而且参数会有差异。启动遇到错误时,可只带参数“--help”查看帮助,比如执行“dockerd --help”。

但如果是yum方式安装的,Docker服务启动配置文件一般均是/usr/lib/systemd/system/docker.service

注意文件docker.service是供系统的systemd使用的,通过命令systemctl来操控。并不是Docker自己的配置文件,实为一个Docker启动配置,下面分两种分别介绍。

1) 带“--graph”参数

这个实际是老版本的参数名,新版本(如“Docker version 19.03.1”)已改叫--data-root,新版本的参数命名更为具体好理解和记忆。

ExecStart=/usr/bin/docker-current daemon \           --graph /data/docker \           --exec-opt native.cgroupdriver=systemd \           $OPTIONS \           $DOCKER_STORAGE_OPTIONS \           $DOCKER_NETWORK_OPTIONS \           $ADD_REGISTRY \           $BLOCK_REGISTRY \           $INSECURE_REGISTRY

“--graph /data/docker”也可写成“--graph=/data/docker”,效果是一样的。另外,还可通过docker-current的命令行参数“--registry-mirror=”指定images仓库。

在文件docker.service发生变化后,需要执行一次“systemctl daemon-reload”通知systemd重新加载,否则使用的仍然是老的配置。

执行“systemctl restart docker.service”重启启动,然后执行ps命令可看到相关的变化:

# ps aux|grep docker root     21757  0.0  0.0 358584 21060 ?        Ssl  09:45   0:00 /usr/bin/docker-current daemon --graph /data/docker --exec-opt native.cgroupdriver=systemd --selinux-enabled --log-driver=journald -b=none --iptables=false

以镜像“hello-world”为例,它的路径为(注:新版本已使用文件系统overlay2替代aufs):

/data/docker/image/aufs/imagedb/content/sha256/fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e

其中“sha256”后面为镜像“hello-world”内容的sha256值:

# cat /data/docker/image/aufs/imagedb/content/sha256/fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e | openssl dgst -sha256 -hex (stdin)= fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e

2) 带“--data-root”参数

这个是新版本的参数名,命名更为具体好理解和记忆,镜像(image)存放在data目录。

# cat /usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com BindsTo=containerd.service After=network-online.target firewalld.service containerd.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/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=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. LimitNOFILE=infinity 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   [Install] WantedBy=multi-user.target

找到docker.service中“ExecStart”所在行,修改为(镜像存放在data目录):。

ExecStart=/usr/bin/dockerd -H fd:// \           --containerd=/run/containerd/containerd.sock \           --data-root=/data/docker/data \           --exec-root=/data/docker/run

Docker在启动时会自动创建这两个目录,但注意需有创建目录权限。并需记得每次修改docker.service后,需要先执行一次“systemctl daemon-reload”,然后才可执行“systemctl start docker.service”启动,否则报“Warning: docker.service changed on disk. Run 'systemctl daemon-reload' to reload units.”。

启动后可看到如下:

# ps aux|grep docker root     22564  0.6  0.1 593460 63488 ?        Ssl  11:04   0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data/docker/data --exec-root=/data/docker/run

以官方的镜像alpine为例,它的存放位置如下(注:新版本已使用文件系统overlay2替代aufs):

# ls -l /data/docker/data/overlay2/c1b9aec275a2cdf832c9f079389aa63577be6f8371dec164af8cc3e8c7fa77f8/diff 总用量 68 drwxr-xr-x  2 root root 4096 12月 19 23:20 bin drwxr-xr-x  2 root root 4096 12月 19 23:20 dev drwxr-xr-x 15 root root 4096 12月 19 23:20 etc drwxr-xr-x  2 root root 4096 12月 19 23:20 home drwxr-xr-x  5 root root 4096 12月 19 23:20 lib drwxr-xr-x  5 root root 4096 12月 19 23:20 media drwxr-xr-x  2 root root 4096 12月 19 23:20 mnt drwxr-xr-x  2 root root 4096 12月 19 23:20 opt dr-xr-xr-x  2 root root 4096 12月 19 23:20 proc drwx------  2 root root 4096 12月 19 23:20 root drwxr-xr-x  2 root root 4096 12月 19 23:20 run drwxr-xr-x  2 root root 4096 12月 19 23:20 sbin drwxr-xr-x  2 root root 4096 12月 19 23:20 srv drwxr-xr-x  2 root root 4096 12月 19 23:20 sys drwxrwxrwt  2 root root 4096 12月 19 23:20 tmp drwxr-xr-x  7 root root 4096 12月 19 23:20 usr drwxr-xr-x 12 root root 4096 12月 19 23:20 var

其中“c1b9aec275a2cdf832c9f079389aa63577be6f8371dec164af8cc3e8c7fa77f8”为diffID,是一个SHA256值,基于镜像层(layer)文件包的内容计算得到。如果该镜像层是最底层(即没有父镜像层),则该层的diffID便是chainID。镜像层元数据存储在目录/data/docker/data/image/overlay2/layerdb下。

5.8. 查看容器日志

# docker logs -f -t --tail=100 container-id

命令“docker logs”参数说明:

参数名

参数说明

-f

跟踪(follow)实时日志

-t

显示时间戳(timestamps)

--tail=N

显示最后N条,如果不指定tail则默认是所有

--details

显示详细信息

--since=

显示某个时间后的日志,或者最近多长时间的日志: 1) --since=10m 查看最近10分钟的日志 2) --since="2019-12-19" 查看2019-12-19后的日志

--until

查看截止到指定时间的日志

5.9. 查看容器列表

1) 查看所有容器

包括已停止的和运行中的容器:

# docker ps -a

命令“docker ps”可选参数:

参数名

参数说明

-a

列出当前所有正在运行的容器和历史上运行过的容器,如果运行容器时没有指定参数“--rm”,则容器退出后“docker ps -a”仍然看得到。

-l

显示最新创建的容器,包括已停止的容器

-n

显示最近n个创建的容器,包括已停止的容器

-q

安静模式,只显示容器编号

--no-trunc

不截断输出

2) 只查看运行中的容器

# docker ps

3) 只查看已停止的容器

# docker ps -a -f status=exited

5.10. 优雅停止容器

先向容器进程发送信号SIGTERM,10秒后再发送SIGKILL。

# docker stop

优雅停止所有容器:

# docker stop $(docker ps -a -q)

5.11. 强制停止容器

直接向容器进程发信号SIGKILL。

# docker kill

5.12. 删除容器

1) 删除一个或多个容器:

# docker rm [OPTIONS] CONTAINER [CONTAINER...]

2) 删除所有的容器:

# docker rm $(docker ps -a -q)

3) 删除所有已停止的容器:

docker rm $(docker ps -a -f status=exited -q)

OPTIONS可取值:

取值

作用

-f

通过SIGKILL信号强制删除一个运行中的容器

-l

移除容器间的网络连接,而非容器本身

-v

删除与容器关联的卷

5.13. 删除镜像

删除指定ID的镜像:

# docker rmi

删除全部镜像:

# docker rmi $(docker images -q)

5.14. 导出镜像

导出镜像到文件,导出后可以文件复制到其它机器再导入:

docker save -o 文件名.tar 镜像名称

如果镜像不在根目录,则需指定目录,如:

docker save -o tinycore.tar tatsushid/tinycore

如果不是Docker的官方仓库,还得指定仓库地址,如:

docker save -o tinycore.tar docker.io/tatsushid/tinycore

5.15. 导入镜像

docker load < 文件名.tar 或 docker load -i 文件名.tar

5.16. 查找镜像

只知道镜像名或部分名,不知道完整的路径时,可以使用Docker提供的查找(search)功能,比如搜索镜像alpine,其中列OFFICIAL指定该镜像是否为Docker官方提供。

# docker search alpine INDEX     NAME                            DESCRIPTION                                 STARS OFFICIAL AUTOMATED docker.io docker.io/alpine                A minimal Docker image based on Alpine Lin... 5927  [OK]        docker.io docker.io/frolvlad/alpine-glibc Alpine Docker image with glibc (~12MB)        223   [OK] docker.io docker.io/mhart/alpine-node     Minimal Node.js built on Alpine Linux         448    docker.io docker.io/anapsix/alpine-java   Oracle Java 8 (and 7) with GLIBC 2.28 over... 434   [OK] docker.io docker.io/gliderlabs/alpine     Image based on Alpine Linux will help you ... 180    docker.io docker.io/alpine/git            A  simple git container running in alpine ... 109   [OK] docker.io docker.io/mvertes/alpine-mongo  light MongoDB container                       106   [OK] docker.io docker.io/alpine/socat          Run socat command in alpine container         43    [OK] docker.io docker.io/zzrot/alpine-caddy    Caddy Server Docker Container running on A... 35    [OK] docker.io docker.io/easypi/alpine-arm     AlpineLinux for RaspberryPi                   32     docker.io docker.io/jfloff/alpine-python  A small, more complete, Python Docker imag... 32    [OK] docker.io docker.io/byrnedo/alpine-curl   Alpine linux with curl installed and set a... 28    [OK] docker.io docker.io/hermsi/alpine-sshd    Dockerize your OpenSSH-server with rsync a... 26    [OK] docker.io docker.io/hermsi/alpine-fpm-php Dockerize your FPM PHP 7.4 upon a lightwei... 21    [OK] docker.io docker.io/zenika/alpine-chrome  Chrome running in headless mode in a tiny ... 16    [OK] docker.io docker.io/bashell/alpine-bash   Alpine Linux with /bin/bash as a default s... 14    [OK] docker.io docker.io/spotify/alpine        Alpine image with `bash` and `curl`.          9     [OK] docker.io docker.io/tenstartups/alpine    Alpine linux base docker image with useful... 9     [OK] docker.io docker.io/roribio16/alpine-sqs  Dockerized ElasticMQ server + web UI over ... 7     [OK]

5.17. 进入容器

容器是运行中的镜像,Docker提供了两种进入运行中容器的途径:

1) 命令“docker container attach

docker container attach [OPTIONS] CONTAINER-ID

示例:

docker container attach 2896d0dad64d

“attach”方式进入容器后,在其中执行“exit”会退出容器(执行“docker ps”将看不到容器还在运行中),原因是attach不会打开新的终端。

2) 命令“docker container exec

docker container exec [OPTIONS] CONTAINER-ID COMMAND [ARG...]

示例:

docker container exec -it 579f618416ca /bin/bash

“docker container exec”的参数和“docker run”相似,不同于attach方式,exec方式进入容器会打开一个新的终端和起一个新的进程,因此exec方式执行exit退出不会导致容器退出(执行“docker ps”仍然看得到容器运行中)。

5.18. 复制文件到容器

借助“docker cp”命令可以将本地文件复制到容器中:

# docker cp --help   Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-         docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH   Copy files/folders between a container and the local filesystem   Use '-' as the source to read a tar archive from stdin and extract it to a directory destination in a container. Use '-' as the destination to stream a tar archive of a container source to stdout.   Options:   -a, --archive       Archive mode (copy all uid/gid information)   -L, --follow-link   Always follow symbol link in SRC_PATH

示例(将当前目录下的文件abc复制到容器0eae45845fc3的根目录,0eae45845fc3相当于进程号,执行“docker ps”可看到):

# docker cp abc 0eae45845fc3:/

注意容器退出后,复制过去的文件将不会保留,但如果是容器挂载的宿主及目录,则容器重启仍然存在。如果需要持久有效,则应执行命令“docker commit”提交到仓库,这样产生了新的镜像。

5.19. 从容器复制文件

方法同复制文件到容器,如将容器中的文件/abc复制到本地的/tmp目录:

# docker cp 0eae45845fc3:/abc /tmp

5.20. 保存容器

修改容器中的文件,或者往容器中新增文件,均不会影响到容器对应的镜像。如果想将新增和修改保存下来,则应执行命令“docker commit”提交到仓库,但这样产生了新的镜像,这新的镜像建立在原镜像层(layer)上。

# docker commit --help   Usage:  docker commit [OPTIONS] CONTAINER-ID [REPOSITORY[:TAG]]   Create a new image from a container's changes   Options:   -a, --author string    Author (e.g., "John Hannibal Smith ")   -c, --change list      Apply Dockerfile instruction to the created image   -m, --message string   Commit message   -p, --pause            Pause container during commit (default true)

6. Docker命令

Docker采用GO语言实现的,他的命令参数为GO风格,参数名和参数值间可以是单个等号或者单个空格或者连续多个空格。其中单字母参数名以单个横杠(即“-”,如:-f)打头,多字母参数名则以两个横杠(即“--”,如:--file)打头。另外,所有Docker命令均可通过参数“--help”得到使用帮助和参数说明。

6.1. 命令“docker build”

命令“docker build”用来构建(生成)镜像,执行“docker build --help”可得到该命令的帮助。

命令“docker build”和“docker run”两者有很多相同参数名,并且很多作用也是相同的,区别在于“docker build”是构建镜像时指定,而“docker run”则是在启动容器时指定,“docker run”能够覆盖“docker build”的同名同作用的参数。

命令“docker build”它的常用参数说明如下:

参数名

参数说明

-f或--file

指定Dockerfile文件,默为当前目录下的Dockerfile,示例: # docker build --tag echo -f Dockerfile.echo . 或 # docker build --tag echo -f=Dockerfile.echo . 或 # docker build --tag echo --file Dockerfile.echo . 或 # docker build --tag echo --file=Dockerfile.echo .

-t或--tag

指定镜像的名(name)和标签(tag),其中标签是可选的,格式“name:tag”

-m或--memory

指定容器最大可用内存,可带单位(不区分大小写): b、k、kb、m、mb、g、gb、t、tb、p、pb 不指定单位为字节数,但不能小于4M,值可大于实际的物理内存。容器中看到的物理内存大小仍然是宿主机的物理内存大小,并不受参数“-m”值的影响。

--memory-swap

内存+交换分区大小总限制,默认值为参数“-m”值的两倍,并且其值必须大于参数“-m”的值。值的格式同参数“-m”,两者差值即为交换分区大小,值-1表示不做限制。 如果只修改“-m”的值,并不会自动更新“--memory-swap”的值。只是如果不指定时,“--memory-swap”的默认值等于“-m”的值的两倍。 容器内的进程占用的内存大小不能超过“-m”和“--memory-swap”两者值之和,否则会被KILL掉。

--ulimit

设置容器的ulimit,示例: # docker build --tag echo --ulimit=nofile=1235 --ulimit=nproc=235 .

--rm

成功构建后删除中间环节的容器,默认为true(即:--rm=true)

--force-rm

总是删除掉中间环节的容器,默认为false(即:--force-rm=false)

-q或--quiet

安静模式,构建成功只输出镜像ID,默认为false(即:--quiet=false)

--network

设置容器运行时的网络模式,默认值是default(即:--network=default),可取值: 1) bridge 容器的默认网络,执行命令“docker inspect bridge”可查看配置 2) none 不为容器创建任何网络,容器将只能使用loopback,即禁用所有联网 3) host 容器使用宿主机的网络,17.06及以上版本才有效 4) container: 5) |   Docker安装的时候默认会创建三个不同的网络,可以执行命令“docker network ls”命令查看这些网络。

--no-cache

构建镜像过程中不使用缓存

--pull

总是尝试拉取镜像的更新版本

--iidfile

将镜像ID写到指定文件,如: # docker build --tag echo --iidfile=myimage.id .

--add-host

添加主机名和主机IP的映射,结果反映在容器的/etc/hosts文件,在/etc/hosts中可以看到添加的映射。 示例: # docker build --add-host=H1:192.168.0.1 --add-host=H2:192.168.0.2 .

--cpu-period

设置CPU CFS的调度周期,单位为微秒(us),取值范围为“1000us~1000000us”,即:1000~1000000。默认值为100000(即100ms),即一个调度周期时长为100ms。

--cpu-quota

设置容器的CPU CFS配额,即在一个“--cpu-period”周期内最多占用CPU的时长,单位为微秒(us)。值不能小于1000us,即不能小于1000,值-1表示不做控制。可大于“--cpu-period”的值,当大于“--cpu-period”的值时相当于占满了整个“--cpu-period”周期。

-c或--cpu-shares

CPU的共享权值(相对权重)

--cpuset-cpus

允许使用的CPU集,可取值:0-3、0或1

--cpuset-mems

对NUMA架构有效,可取值:0-3、0或1

6.2. 命令“docker run”

命令“docker run”用来启动容器,参数比较多,包括各资源配额等参数,执行“docker run --help”可得到该命令的帮助。

参数名

参数说明

-d或--detach

以后台方式启动容器

--name

设置容器名,类似进程名

--rm

容器退出后,自动删除容器

-t或--tty

为容器分配一个伪终端

-i或--interactive

交互模式运行容器,保持标准输入打开

--add-host

同“docker build”

--cpu-period

同“docker build”

--cpu-quota

同“docker build”

-c或--cpu-shares

同“docker build”

-m或--memory

同“docker build”

--memory-swap

同“docker build”

--ulimit

同“docker build”

--network

同“docker build”,设置连接的网络类型,如: # docker run -it --rm --network=bridge centos

--network-alias

设置网络别名(列表),自定义网络模式才有效,否则报错“network-scoped aliases are only supported for user-defined networks”。

-u或--user

设置运行容器的用户(也可同时设置用户组),如: # docker run -it --rm -u=dbus centos

--expose

容器对外暴露的端口(列表),会覆盖Dockerfile中定义的EXPOSE端口,如: # docker run -it --rm --expose 2019 --expose 2020 centos   注意这只是一个声明,容器中是否有开启这个端口由容器中的程序决定。

-v或--volume

指定容器绑定的本地目录

--link

设置要连接的其它容器(列表),如: # docker run -it --rm --link=20cf8c99379e centos

--restart

容器重启策略: 1) no 默认值,表示表示容器退出时,Docker不自动重启容器 2) always 只要容器退出,Docker均重启容器 3) on-failure 容器退出状态值非0时,Docker自动重启容器

--pids-limit

设置容器内最多进程数,默认为-1表示不做限制

--oom-kill-disable

禁止容器内的OOM

--pid

和指定容器共享PID(进程ID)资源,如: # docker run -it --rm --pid=container:4aae83be7a11 centos

--env

设置容器的环境变量

--env-file

设置容器的环境变量,环境变量来源于文件

6.3. 命令“docker update”

“docker run”可以通过参数覆盖“docker build”时指定的值,而“docker update”又可实时修改“docker run”和“docker build”时指定或未指定的值。

“docker update”能够修改的参数如下表所示:

参数名

参数说明

--cpu-period

同“docker run”

--cpu-quota

同“docker run”

-c或--cpu-shares

同“docker run”

-m或--memory

同“docker build”

--memory-swap

同“docker run”

--restart

同“docker run”

--pids-limit

同“docker run”

7. 常见问题

7.1. failed to create NAT chain DOCKER

执行“systemctl start docker.service”试图启动docker时报如下错误:

# systemctl -l status docker.service failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found docker.service: main process exited, code=exited, status=1/FAILURE Failed to start Docker Application Container Engine. Unit docker.service entered failed state.

这个错误是因为没有启动iptables,导致Docker无法做端口转发,执行命令“systemctl status firewalld”查看防火墙状态:

# systemctl status firewalld firewalld.service - firewalld - dynamic firewall daemon    Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)    Active: inactive (dead)

firewalld没有起来,启动它(disabled表示不随系统自动启动):

# systemctl start firewalld # systemctl status firewalld firewalld.service - firewalld - dynamic firewall daemon    Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)    Active: active (running) since 三 2019-12-18 16:14:07 CST; 4s ago  Main PID: 8066 (firewalld)    CGroup: /system.slice/firewalld.service            └─8066 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid   12月 18 16:14:07 X.site systemd[1]: Started firewalld - dynamic firewall daemon.

在CentOS7中虽然iptables仍然存在,但请使用firewalld来取代iptables服务。执行“systemctl start iptables”启动iptables,将会自动停止firewalld,所以不要启动iptables.service。

7.2. Failed to start firewalld - dynamic firewall daemon

执行“systemctl status firewalld.service”时报如下错误:

# systemctl status firewalld.service firewalld.service - firewalld - dynamic firewall daemon    Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)    Active: failed (Result: exit-code) since 三 2019-12-18 15:46:41 CST; 4s ago   Process: 6381 ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS (code=exited, status=1/FAILURE)  Main PID: 6381 (code=exited, status=1/FAILURE)   12月 18 15:46:41 X.site systemd[1]: firewalld.service: main process exited, code=exited, status=1/FAILURE 12月 18 15:46:41 X.site systemd[1]: Failed to start firewalld - dynamic firewall daemon. 12月 18 15:46:41 X.site systemd[1]: Unit firewalld.service entered failed state.

上述错误信息不是很明确,不足以分析出问题。/usr/sbin/firewalld实际上是一个Python脚本,由/usr/lib/systemd/system/firewalld.service中定义拉起firewalld:

ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS

可手工执行看看情况:

ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS

手工执行:

# /usr/sbin/firewalld --nofork --nopid Traceback (most recent call last):   File "/usr/sbin/firewalld", line 34, in     from firewall import config ImportError: No module named firewall

错误信息显示没有名为firewall的Python模块(修复这个后,仍然可能缺失其它模块,需逐一排查,查看文件/usr/sbin/firewalld可了解到所依赖的其它模块),简单点可直接从其它机器复制一份过来。先找到firewall在其它机器上的位置:

# python Python 2.7.5 (default, Nov 20 2015, 02:00:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import firewall >>> print firewall.__file__ /usr/lib/python2.7/site-packages/firewall/__init__.pyc >>>

注意,不同机器Python包的位置可能不同,可查看sys.path值来确认包存放在哪些目录下。

另外,请注意/usr/sbin/firewalld中使用的Python是否正确(注意python的路径):

# head -1 /usr/sbin/firewalld #!/usr/bin/python -Es

7.3. can't initialize iptables table `nat'

执行命令“iptables -t nat -F”时报如下错误:

# iptables -t nat -F iptables v1.4.21: can't initialize iptables table `nat': Table does not exist (do you need to insmod?) Perhaps iptables or your kernel needs to be upgraded.

遇到这个错误时,可能需要重新配置和编译内核。执行命令“modinfo iptable_nat”检查内核中是否有NAT模块:

# modinfo iptable_nat modinfo: ERROR: Module iptable_nat not found.

如果没有条件编译内核,则可从其它地方将相关的模块文件复制过来,复制过来后注意需执行一次depmod命令。相关路径:“/lib/modules/`uname -r`”。

如果模块存在,则显示如下(内核模块文件名以“.ko”为后缀,ko为“Kernel Object”的缩写,depends显示依赖的其它模块):

# modinfo iptable_nat filename:       /lib/modules/3.10.107-1-0050/kernel/net/ipv4/netfilter/iptable_nat.ko license:        GPL srcversion:     22FC08135673BF996B25929 depends:        nf_nat,ip_tables,nf_nat_ipv4,nf_conntrack intree:         Y vermagic:       3.10.107-1-0050 SMP mod_unload modversions signer:          sig sig_key:        6E:69:6E:67:20:6B:65:79:2C:94:15:C6:82:EA:DB:06:CF:5A:37:57:72:EE:7A:58:2D:CA:23:38 sig_hashalgo:   sha512

其它模块可同样方法查看:

# modinfo nf_nat filename:       /lib/modules/3.10.107-1-0050/kernel/net/netfilter/nf_nat.ko license:        GPL srcversion:     5A7A5091ADF09B929C3EBC8 depends:        nf_conntrack intree:         Y vermagic:       3.10.107-1-0050 SMP mod_unload modversions signer:          sig sig_key:        6E:69:6E:67:20:6B:65:79:2C:94:15:C6:82:EA:DB:06:CF:5A:37:57:72:EE:7A:58:2D:CA:23:38 sig_hashalgo:   sha512

7.4. list bridge addresses failed

执行“systemctl start docker.service”时报如下错误:

12月 18 16:26:19 X.site dockerd[23727]: failed to start daemon: Error initializing network controller: list bridge addresses failed: PredefinedLocalScopeDefaultNetworks List: [172.17.0.0/16 172.18.0.0/16 172.19.0.0/16 172.20.0.0/16 172.21.0.0/16 172.22.0.0/16 172.23.0.0/16 172.24.0.0/16 172.25.0.0/16 172.26.0.0/16 172.27.0.0/16 172.28.0.0/16 172.29.0.0/16 172.30.0.0/16 172.31.0.0/16 192.168.0.0/20 192.168.16.0/20 192.168.32.0/20 192.168.48.0/20 192.168.64.0/20 192.168.80.0/20 192.168.96.0/20 192.168.112.0/20 192.168.128.0/20 192.168.144.0/20 192.168.160.0/20 192.168.176.0/20 192.168.192.0/20 192.168.208.0/20 192.168.224.0/20 192.168.240.0/20]: no available network 12月 18 16:26:19 X.site systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE 12月 18 16:26:19 X.site systemd[1]: Failed to start Docker Application Container Engine. 12月 18 16:26:19 X.site systemd[1]: Unit docker.service entered failed state.

这个错误是因为没有网桥(可执行命令“ip a”或“netstat -ie”等检查),导致docker无法启动。执行以下命令创建和启动网桥:

# ip link add name docker0 type bridge # ip addr add dev docker0 172.17.0.1/16 # ip link set docker0 up # ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00     inet 127.0.0.1/8 scope host lo        valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc noop state DOWN qlen 1000     link/ether 60:eb:69:fe:2e:20 brd ff:ff:ff:ff:ff:ff 3: eth1: mtu 1500 qdisc mq state UP qlen 1000     link/ether 60:eb:69:fe:2e:21 brd ff:ff:ff:ff:ff:ff     inet 10.22.25.101/26 brd 10.223.25.127 scope global eth1        valid_lft forever preferred_lft forever 4: docker0: mtu 1500 qdisc noqueue state UNKNOWN     link/ether 6e:3c:cb:3e:a7:44 brd ff:ff:ff:ff:ff:ff     inet 172.17.0.1/16 scope global docker0        valid_lft forever preferred_lft forever

创建网桥也可使用专门的工具brctl

7.5. No module named yum

在执行yum命令时,如果报如下错误:

# yum There was a problem importing one of the Python modules required to run yum. The error leading to this problem was:      No module named yum   Please install a package which provides this module, or verify that the module is installed correctly.   It's possible that the above module doesn't match the current version of Python, which is: 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)]   If you cannot solve this problem yourself, please go to the yum faq at:   http://yum.baseurl.org/wiki/Faq

命令yum实为Python脚本,这个错误表示找不到名为yum的Python模块。检查Python的模块搜索路径:

# python Python 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> print sys.path ['', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages', '/usr/lib/python2.7/site-packages/setuptools-34.4.1-py2.7.egg', '/usr/lib/python2.7/site-packages/MySQL_python-1.2.5-py2.7-linux-x86_64.egg'] >>>

如果模块yum可用,可通过如下方法找到它所有路径:

# python >>> import yum >>> print yum.__file__ /usr/lib/python2.7/site-packages/yum/__init__.pyc

如果模块yum并不存在,则可从其它可用的机器复制一份过来,保持目录一致。如果在执行“import yum”报错“No module named urlgrabber”和“No module named rpmUtils.transaction”,则也需要将urlgrabber等模块复制过来,直到“import yum”不再报错。

7.6. rpmdb open failed

执行“yum install docker-ce-19.03.5-3.el7.x86_64.rpm”时报如下错误:

# yum install docker-ce-19.03.5-3.el7.x86_64.rpm error: rpmdb: BDB0113 Thread/process 7020/140405160273920 failed: BDB1507 Thread died in Berkeley DB library error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery error: cannot open Packages index using db5 -  (-30973) error: cannot open Packages database in /var/lib/rpm CRITICAL:yum.main:   Error: rpmdb open failed

这个错误是因为RPM数据库损坏了,执行以下操作的修复:

# cd /var/lib/rpm # tar czf x.tar.gz __db.* # rm -f __db.* # rpm --rebuilddb # yum clean all

然后,可再次执行“yum install docker-ce-19.03.5-3.el7.x86_64.rpm”。

7.7. start request repeated too quickly for docker.service

执行“systemctl start docker.service”时报如下错误:

systemd[1]: start request repeated too quickly for docker.service systemd[1]: Failed to start Docker Application Container Engine. systemd[1]: Unit docker.service entered failed state. systemd[1]: docker.service failed.

“systemctl start docker.service”输出的信息可能不全,可直接查看系统日志文件/var/log/messages,如果看到以下错误信息:

Running modprobe nf_nat failed with message: `modprobe: WARNING: Module nf_nat not found.`, error: exit status 1

该错误表示没有加载内核模块“iptable_nat”,执行“modinfo iptable_nat”确认:

# modinfo iptable_nat modinfo: ERROR: Module iptable_nat not found.

7.8. Module nf_nat not found

该错误表示没有加载内核模块“iptable_nat”,模块文件位于目录/lib/modules/`uname -r`/kernel/。

# ls /lib/modules/`uname -r`/kernel/ arch  crypto  drivers  fs  kernel  lib  mm  net

内核模块“iptable_nat”又依赖nf_nat和ip_tables等内核模块,成功加载后问题将解决。

# lsmod | grep nat iptable_nat            13011  1 nf_nat_ipv4            13263  1 iptable_nat nf_nat                 26711  3 ipt_MASQUERADE,nf_nat_ipv4,iptable_nat nf_conntrack           96187  8 ipt_MASQUERADE,nf_nat,nf_nat_ipv4,xt_conntrack,nf_conntrack_netlink,iptable_nat,nf_conntrack_ipv4,nf_conntrack_ipv6 ip_tables              27239  4 iptable_filter,iptable_mangle,iptable_nat,iptable_raw

7.9. applying cgroup configuration for process caused

启动容器时报如下错误:

Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "process_linux.go:258: applying cgroup configuration for process caused \"Cannot set property TasksAccounting, or unknown property.\"".

这个错误是因为镜像和Linux内核版本不一致,一般是镜像要求更高版本的内核,因此需要升级内核。

7.10. Transaction check error:

执行“yum -y install docker-ce”时报如下错误:

Transaction check error:   file /usr/bin/docker from install of docker-ce-cli-1:19.03.1-3.el7.x86_64 conflicts with file from package docker-common-2:1.13.1-96.gitb2f74b2.tl2.x86_64   file /usr/bin/dockerd from install of docker-ce-3:19.03.1-3.el7.x86_64 conflicts with file from package docker-common-2:1.13.1-96.gitb2f74b2.tl2.x86_64   错误概要 -------------

这是依赖包版本冲突问题,需先执行“yum -y remove docker-common”删除依赖的包“docker-common”,然后再执行“yum -y install docker-ce”。

7.11. Your kernel does not support swap limit capabilities or the cgroup is not mounted

启动容器时遇到如下错误:

Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.

执行命令“lssubsys --all”检查是否安装了cgroups相关组件,如果执行“yum install -y cgroup-bin”或“yum install -y libcgroup libcgroup-tools”安装。

进一步检查是否打开了内核的“cgroup_enable”和“swapaccount”,如果没有则可编辑/etc/default/grub,为GRUB_CMDLINE_LINUX所在行添加如下内容:

cgroup_enable=memory swapaccount=1

在修改文件/etc/default/grub后,得执行命令“/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg”以将/etc/default/grub更新到/boot/grub2/grub.cfg,然后还需重启系统以生效。

7.12. Cannot connect to the Docker daemon at

启动容器时遇到如下错误:

docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?. See 'docker run --help'.

这个错误是因为没有启动Docker服务。

7.13. Minimum memoryswap limit should be larger than memory limit

执行“docker update”时报如下错误:

Error response from daemon: Minimum memoryswap limit should be larger than memory limit, see usage

这是因为参数“--memory-swap”的值小于参数“-m”的值。

附1:rpm安装

RPM包实际也是一个压缩包,为“RedHat Package Manager”的缩写,在Windows上可用7-zip等软件直接打开见其卢山真面目。以下是RPM命令的常见应用:

命令

作用

说明

rpm -ivh packagename.rpm

安装

-i为install之意,即安装,等同--install; -v为verbose之意,即显示详细信息,等同--verbose; -h为hash之意,即显示进度信息,等同--hash。

rpm -ivh packagename.rpm --nodeps

强制安装,并忽略依赖

rpm -ivh packagename.rpm --force

强制安装,不忽略依赖

rpm -e packagename

卸载

rpm -qi packagename

查看信息

rpm -pq packagename.rpm

查询安装后的名字

rpm -ql packagename

查询安装后生成的文件

rpm -qlp packagename.rpm

查询安装后生成的文件

RPM没有解决包依赖问题,所以使用它安装时,可能会遇到很多依赖包版本不匹配或者依赖的包不存在问题。就Docker而言,使用RPM包安装,可能并不简单,如果不能yum安装,则更建议直接二进制安装。

Docker RPM包可在https://download.docker.com/linux/centos/7/x86_64/stable/Packages/上找到。

container-selinux等部分包可在http://mirror.centos.org/centos/7/extras/x86_64/Packages/上找到。

附2:yum安装

Linux上的yum是一个Python脚本,为“Yellow dog Updater, Modified”的缩写,基于RPM的Shell前端软件包管理器。

/etc/yum.conf为yum的配置文件,仓库配置放在目录/etc/yum.repos.d下。如果需添加本地仓库,可在目录/etc/yum.repos.d下新建一仓库配置,然后清除下缓存,执行“yum repolist”即可看到。

以下是yum命令的常见应用:

命令

作用

说明

yum list all

列举出仓库中的所有包

yum list installed

列举已安装的

yum list available

列举可安装的包

yum repolist all

列举出所有仓库,含禁用的

yum repolist

列举出可用的仓库

等同“yum repolist enabled”

yum repolist disabled

列举出禁用的仓库

yum clean all

清除所有缓存

yum search packagename

查找可安装的包

示例: yum search docker

yum info packagename

查询包的摘要信息

示例: yum info docker

yum deplist packagename

查看包依赖

示例: yum deplist docker

yum list all packagename

查看仓库中指定名的包

救命: yum list all docker

yum -y install packagename

安装

示例1(安装单个): yum -y install docker   示例2(安装多个): yum -y install \ docker-ce \ docker-ce-cli \ containerd.io \ docker

yum -y remove packagenameX

删除安装的包

注意packagenameX是命令yum list installed列出的包名(第1列),比如docker-ce-cli.x86_64。   示例1: yum -y remove docker.x86_64 示例2: yum -y remove \ docker-ce-cli.x86_64

yum-config-manager \ --add-repo=ADDREPO

添加和启用一个新的仓库,执行时会在目录/etc/yum.repos.d下生成一个repo文件。

示例: yum-config-manager \ --add-repo=\ https://download.docker.com/linux/centos/docker-ce.repo   如果没有yum-config-manager,则可用下列命令安装: yum install -y yum-utils \ device-mapper-persistent-data \ lvm2   yum-config-manager是包yum-utils中的一员。

附3:systemctl和systemd

常见systemctl用法:

命令

作用

说明

systemctl start service

启动服务

示例1: system start docker.service 或 system start docker

systemctl stop service

停止服务

示例1 system stop crond 或 system stop crond.service

systemctl restart service

重启服务

systemctl enable service

设置服务随系统自动启动

以docker.service为例,“systemctl enable service”的作用实际等同于: ln -s \ '/etc/systemd/system/docker.service' \ '/etc/systemd/system/multi-user.target.wants/docker.service'

systemctl disable service

取消服务随系统自动启动

以docker.service为例,“systemctl disable service”的作用实际等同于: rm '/etc/systemd/system/multi-user.target.wants/docker.service'

systemctl status service

查看服务状态

systemctl reload

重加载配置

当修改诸如docker.service文件时,需要执行一次reload

systemctl reboot

重启系统

systemctl set-default

设置默认的启动级别,其中multi-user.target对应级别3,graphical.target对应级别5

示例1: systemctl \ set-default \ multi-user.target   示例2: systemctl \ set-default \ graphical.target

systemctl类似于Windows平台的服务管理器,工作原理是通过与服务systemd交互完成各项工作,比如重启crond进程。

systemd是Linux系统启动后的第一个进程,取代了以前的init进程。systemd进程和init进程不会同时存在,低版本Linux为init,高版本Linux为systemd。

“systemctl status”和“systemctl -l status”输出的信息实际来源于系统日志文件“/var/log/message”。

当使用“systemctl start”启动一个服务失败,通过“systemctl -l status”又找不到确切原因时,可尝试直接执行service文件(比如docker.service)中ExecStart的定义的命令,这样可能可查明失败原因。

附4:命令brctl

可用brctl命令管理网桥,为包bridge-utils中的一员。

命令

作用

说明

brctl addbr

创建网桥

示例: brctl addbr docker0

brctl delbr

删除网桥

示例: brctl delbr docker0

brctl show

查询网桥信息

brctl setfd

设置网桥转发延迟

示例: brctl setfd docker0 10

brctl addif

网卡接入网桥

示例: brctl addif docker0 eth1

brctl delif

删除接入网桥的网卡

brctl stp

启用网桥

示例: brctl stp docker0 on

brctl stp

禁用网桥

brctl showmacs

查看mac信息

示例: brctl showmacs docker0

附5:命令ip

Linux中网格管理命令,功能覆盖ifconfig、netstat、route、arp等命令,是一个十分强大的大而全集成工具。为包iproute中的一员,而netstat和ifconfig为包net-tools包中的一员(执行“rpm -ql net-tools”可查看)。

常见对比:

Ifconfig/netstat命令

ip命令

归属包

net-tools

iproute

ifconfig

ip link

ifconfig eth0 up

ip link set eth0 up

查看所有接口,包括已禁用的

ifconfig -a

ip addr show或ip a

ifconfig -s

ip -s link

netstat -i

ip -s link

netstat -r

ip route

还可使用命令ip创建和设置网桥:

1) 创建网桥

ip link add name docker0 type bridge

注:执行“ip link help”可查看“ip link”的使用帮助。

2) 设置网桥的IP和网关

ip addr add dev docker0 172.17.0.1/16

注:“172.17.0.1/16”中的“172.17.0.1”为网桥的IP地址,16表示16个1,对应的网关地址为255.255.0.0(十填制数255对应的二进制值为11111111)。

3) 启用网桥

ip link set docker0 up

4) 禁用网桥

ip link set docker0 down

5) 删除网桥

ip link delete docker0 type bridge

附6:内核模块

Linux内核模块放在目录/lib/modules/`uname -r`/kernel下,模块文件以“.ko”为后缀:

# file /lib/modules/`uname -r`/kernel/net/netfilter/nf_nat.ko /lib/modules/3.10.107-1-0046/kernel/net/netfilter/nf_nat.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=1a7527386082c922caeb208c7c9a1d530c079f1d, not stripped

1) 查看模块信息

使用命令modinfo查看模块信息

# modinfo xt_limit.ko filename:       /lib/modules/3.10.107-1-0046/kernel/net/netfilter/xt_limit.ko alias:          ip6t_limit alias:          ipt_limit description:    Xtables: rate-limit match author:         Herve Eychenne license:        GPL srcversion:     B22C9E4BCCDBDFBFD5D4EFD depends:         intree:         Y vermagic:       3.10.107-1-0046 SMP mod_unload modversions signer:          sig sig_key:        6E:69:6E:67:20:6B:65:79:2C:94:15:C6:82:EA:DB:06:CF:5A:37:57:72:EE:7A:58:2D:CA:23:38 sig_hashalgo:   sha512

2) 查看已加载模块

使用命令lsmod查看已加载模块列表:

# lsmod Module                  Size  Used by nf_nat                 26754  0 ip6t_rpfilter          12546  1 ip6t_REJECT            12939  2 nf_conntrack_ipv6      18738  4 nf_defrag_ipv6         34651  1 nf_conntrack_ipv6   # lsmod | grep nf_nat nf_nat                 26754  0 nf_conntrack           96187  4 nf_nat,xt_conntrack,nf_conntrack_ipv4,nf_conntrack_ipv6

3) 卸载模块

使用命令rmmod卸载模块:

# rmmod nf_nat_proto_udplite # rmmod nf_nat.ko

4) 加载模块

使用命令insmod加载模块,要求指定模块文件名的全路径或相对路径:

# insmod ./nf_nat_proto_udplite.ko # insmod netfilter/nf_nat.ko

也可使用modprobe加载模块,这种方式不需要指定模块路径。modprobe依靠文件/lib/modules/`uname -r`/modules.dep来查找模块文件,因此当在目录/lib/modules/`uname -r`/kernel下有新增模块文件时,需要先执行一次depmod命令,才能执行modprobe加载模块,否则报错:

# modprobe nf_nat modprobe: FATAL: Module nf_nat not found.

如果模块格式不匹配,将报如下所示错:

# modprobe nf_nat modprobe: ERROR: could not insert 'nf_nat': Exec format error   # insmod ./nf_nat.ko insmod: ERROR: could not insert module ./nf_nat.ko: Invalid module format

5) 更新模块依赖关系

模块依赖关系文件为/lib/modules/`uname -r`/modules.dep,当有在目录/lib/modules/`uname -r`/kernel下新增模块文件后,需要执行一次depmod来更新文件modules.dep,否则modprobe将找不到模块文件。

window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SNMP V3的配置指南

    SNMP v3版本已经推出很久了,但是其普及度一直不高,原因就在于其配置过于复杂,本文主要就以cisco2950、锐捷2600以及H3C 3600系列交换机的S...

    用户2398817
  • Python 与 ODBC 的陷阱

       除了pyodbc还有win32com,熟悉ADO编程的就选择win32com

    用户2398817
  • puppet kick 报错返回值cod

    环境: puppetserver端  RHEL5.8或者RHEL6.4 [root@puppetserver1 etc]# cat /etc/redhat-re...

    用户2398817
  • H3C配置常用命令

    超级用户终端登陆交换机 SYS进入                              //sys进入系统视图 输入以下命令 #  sysname...

    用户2398817
  • 检测阿根廷恰加斯病潜在高流行地区(Computers and Society)

    本文提出了一种具有高空间分集性的恰加斯病(ChD)潜在患病率地图。它的目的是检测大查科生态区域化(恰加斯病的高度地方化)以外的地区,其特征是与恰加斯病高度相关和...

    李欣颖6837176
  • H3C-5500 做的VRRP

    <VRRP-1>dis curr #  version 5.20, Release 2202 #  sysname VRRP-1 #  irf m...

    用户2398817
  • python3_06_01.模块之os

    用户2398817
  • Qt 模拟 HTTP 表单提交文字或文件到服务器

    传统通过 HTTP 表单的方式来上传文件在 Web 中实现是非常简单的,一个表单中加几个域填写上对应的内容提交就可以了,但如果通过 Qt 来实现就相对麻烦一点,...

    我与梦想有个约会
  • H3C综合配置

     6.在RTB上配置NAT以及各路由器的静态路由实现H公司局域网用户通过NAT 转换访问SWC及PCB:

    用户2398817
  • Storefront与NetScaler

    http://kaiqian.blog.51cto.com/blog/236001/1344447

    用户2398817

作者介绍

精选专题

活动推荐

扫码关注云+社区

领取腾讯云代金券