Docker入门之安装Docker
前言
本文操作基于CentOS7,其它Linux发行版本可能存在差异,分基于yum的在线安装和基于二进制包的离线安装(实际还有基于rpm包的离线安装),离线安装可以更多地了解Docker及相关体系。
Docker要求Linux内核版本不低于3.10,并且必须为64位系统,执行命令“docker
version”可查看Docker版本。
CentOS7防火墙默认采用的是firewalld管理netfilter子系统,底层调用的仍然是iptables命令,firewalld实际是iptables的一个封装。不同的防火墙相互间存在冲突,使用某其中一个时应禁用其他的。
创建网桥
启动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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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”而启动失败。
安装Docker
在能访问网络的环境或者有本地Docker仓库的环境,建议使用yum安装,简单省事。
在不能访问网络环境,可手工安装Docker。进入https://download.docker.com/,下载对应的安装包,这里又分两种:一是下载通用的二进制安装包,二是下载RPM安装包。相对yum安装,手工安装(离线安装)可以了解更多细节,有助于深入了解Docker。
二进制安装
这个方法比较复杂,容易遇到各种问题。
下载安装
通用的二进制安装包下载路径: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负责加载images拉起容器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”。
配置服务
新建和编辑文件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”用于指定images存放目录。
启动服务
执行命令“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 |
---|
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包安装涉及很多依赖,安装可能复杂(视实际的依赖程度),所以尽量避免这种安装方式。本文尝试时,因为太多的依赖需要安装或更新,导致未能完成。
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为容器引擎,安装步骤:
添加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为空文件。
安装docker-ce
执行下列命令安装:
# yum -y install 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 |
---|
启动服务
执行命令“systemctl start docker.service”启动Docker:
# systemctl start docker.service # ps aux|grep docker | grep -v grep /usr/bin/docker -d –selinux-enabled -b=none |
---|
Docker基本操作
启动Docker服务
和其它服务一样启动即可,停止和重启方法也相同。
# systemctl start docker.service |
---|
查看有哪些images
# 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? |
---|
从仓库拉取images
默认拉取到的是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 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”]}} |
---|
运行image
以“hello-world”为例:
# docker run 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/ |
---|
查看指定的image
# docker inspect hello-world [ { “Id“: “sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e“, “RepoTags”: [ “docker.io/hello-world:latest” ], 。。。 。。。 |
---|
修改images存放目录
对于CentOS7,修改文件/usr/lib/systemd/system/docker.service,为docker-current指定命令行参数–graph,比如将目录设置为/data/docker。
注意有些版本的叫/usr/bin/docker-current,有些叫/usr/bin/docker,有些叫/usr/bin/dockerd,而且参数会有差异。启动遇到错误时,可只带参数“–help”查看帮助,比如执行“dockerd
–help”。
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”为例,它的路径为:
/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 |
---|
查看运行中的容器
# docker ps |
---|
优雅停止容器
先向容器进程发送信号SIGTERM,10秒后再发送SIGKILL。
# docker stop |
---|
强制停止容器
直接向容器进程发信号SIGKILL。
# docker kill |
---|
附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 <bridge> | 创建网桥 | 示例: brctl addbr docker0 |
brctl delbr <bridge> | 删除网桥 | 示例: brctl delbr docker0 |
brctl show <bridge> | 查询网桥信息 | |
brctl setfd <bridge> <time> | 设置网桥转发延迟 | 示例: brctl setfd docker0 10 |
brctl addif <bridge> <device> | 网卡接入网桥 | 示例: brctl addif docker0 eth1 |
brctl delif <bridge> <device> | 删除接入网桥的网卡 | |
brctl stp <bridge> <on> | 启用网桥 | 示例: brctl stp docker0 on |
brctl stp <bridge> <off> | 禁用网桥 | |
brctl showmacs <bridge> | 查看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创建和设置网桥:
- 创建网桥
ip link add name docker0 type bridge |
---|
注:执行“ip link help”可查看“ip link”的使用帮助。
- 设置网桥的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)。
- 启用网桥
ip link set docker0 up |
---|
- 禁用网桥
ip link set docker0 down |
---|
- 删除网桥
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 |
---|
- 查看模块信息
使用命令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 <rv@wallfire.org> 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 |
---|
- 查看已加载模块
使用命令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 |
---|
- 卸载模块
使用命令rmmod卸载模块:
# rmmod nf_nat_proto_udplite # rmmod nf_nat.ko |
---|
- 加载模块
使用命令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 |
---|
- 更新模块依赖关系
模块依赖关系文件为/lib/modules/`uname
-r`/modules.dep,当有在目录/lib/modules/`uname
-r`/kernel下新增模块文件后,需要执行一次depmod来更新文件modules.dep,否则modprobe将找不到模块文件。
附7:常见问题
- 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。
- 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 <module> 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 |
---|
- 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 |
---|
- 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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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。
- 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”不再报错。
- 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”。
- 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. |
---|
- 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 |
---|