15.应用和管理Podman及Docker容器
15.应用和管理Podman及Docker容器
容器(Container)是一种内核级别的隔离技术,而对于CentOS 8而言,主要的容器工具为最新的Podman,而之前CentOS 6/7系统,Docker则是最为流行的容器技术,其也是一款面向开发者的工具,由Docker.Inc公司的基于dotCloud的Container容器引擎发展而来的,二者都是基于Google的Go语言开发,其源代码托管在GitHub上, 具体地址如下:
Podman项目地址如下:
https://github.com/containers/libpod
Docker项目地址如下:
https://github.com/docker/docker
15.1.Podman和Docker容器必知必会
Podman是RHEL/CentOS 8所主推的容器技术,号称是下一代的容器技术,由Red Hat发起并维护的开源容器项目,将成为支持各发行版自带的容器管理实现,支持docker.io和quay.io等容器技术,Podman项目的Logo如图15-1所示。
图15-1 Podman项目Logo
Podman官方地址如下:
https://podman.io/
而Docker则是一个采用Apache 2.0开源协议的容器开源项目,比Podman更加成熟一点,目前几乎所有主流操作系统和公司都支持。此外,通过Docker的Compose,Swarm和Machine项目的支撑,可以将多个Docker Engine整合成为一个更大的Docker Engine,类似于Linux系统的集群服务,可以像使用单个Docker一样使用Docker集群,Docker的Logo是一条鲸鱼,十分可爱,如图15-2所示。
图15-2 Docker可爱的Logo
Docker最擅长用来隔离应用,不但操作简单便捷,而且更加安全,容器间的通信通过加密和端口转发,更重要的是资源占用比虚拟机小得多。Docker采用典型的客户端/服务器 (C/S) 架构。Docker守护进程Docker容器的管理,如创建,运行和发布用户的Docker容器。需要注意的是,Docker 客户端和守护进程之间既可以通过传统的Socket进行通信也可以采用目前互联网环境流行的RESTful API进行通信,比较灵活。
Tips:Docker Engine和Docker Machine是一个东西吗?
Docker通常是指Docker Engine,而Docker Engine则是一个典型客户端/服务器(C/S)架构的程序,其主要由如下两部分构成:
◆Docker Client:Docker客户端是用户端程序,用于与Docker服务端进行通信
◆Docker Server:Docker的服务端守护进程,负责处理服务请求
Docker Machine则是部署和管理Docker Egine程序的一个工具,可在各种平台上便捷地创建Docker Host(装有Docker Engine的虚拟机),千万不要将二者混为一谈,使用起来最明显的差异就是Docker Engine的命令是docker,而Docker Machine的命令则是docker-machine。
Docker主要由如下几个部件构成:
◆Docker: 主流容器开源项目
◆Docker Hub: 基于云计算的Docker容器注册和索引服务,主要通过互联网分享,保存和管理Docker容器,一个重要的Docker在线镜像仓库,其模式十分类似Github代码托管服务,Docker Hub地址如下:
https://hub.docker.com
Tips:Docker的两个亲兄弟Compose和Swarm
Docker的主体是Docker Engine,是Docker的运行环境,亦是一个跨平台的工具,支持主流平台,如Windows,Linux和Mac等系统,有道是一个好汉两个帮,与Docker密切相关的两个原生项目是Compose和Swarm。
◆Compose
Compose主要是解决本地Docker容器编排问题,所谓容器编排,可以理解为容器的批处理或脚本,只不过是通过yaml格式的配置文件来实现的,Yaml文件可记录一个或多个容器启动的配置,如镜像,端口映射和启动命令等,写好的yaml文件只需要运行docker-compose相应命令执行,可以极大地提高Docker部署和应用的效率,是高效使用Docker不可或缺的工具。
◆Swarm
Swarm的功能和Compose类似,不过swarm主要是用于解决多主机多容器的调度和部署,是基于Docker平台的原生集群技术,可以实现简单高效地创建Docker集群,进而部署应用,最终实现分布式的服务。和流行的Kubernetes相比,Swarm项目还不是很成熟,故使用Kubernetes来管理Docker集群和调度似乎更加流行。
不过由于CentOS 8官方已经不再支持Docker了,虽然有一些方法可以在CentOS 8上安装好Docker,但也仅限于能够安装上,Docker的很多功能是无法正常使用的,正因为此原因,建议在CentOS 8中通过KVM运行CentOS 7,并在7的环境安装和使用Docker,对于CentOS 8而言,使用Podman可能是目前最好的选择了。
15.2 掌握无守护进程容器管理工具Podman
Podman可以管理和运行任何符合OCI(Open Container Initiative)规范的容器和容器镜像,更为重要的是,Podman提供了一个与Docker兼容的命令行前端来管理镜像。Podman是一个类似Docker的容器管理工具,但其不需要像Docker引擎那样必须用超级用户权限以守护进程的形式运行在后台。Podman无需守护进程,所以能在一定程度上节约系统开销。
更为重要的是,Podman既可以让容器以超级用户身份运行,也可以普通用户身份运行,这一特征有效的提升了容器部署的灵活性,下面为了演示方便,笔者将以超级用户身份运行Podman,推荐大家使用普通用户运行更为安全。
◆安装Podman
运行如下命令安装Podman:
dnf install podman -y
成功安装后,可以使用如下命令查看Podman的版本:
podman version
Version: 1.0.5
Go Version: go1.11.6
OS/Arch: linux/amd64
总体来说,Podman的使用和Docker十分类似,大家可以如法炮制,灵活地将Docker使用方法和经验快速迁移到Podman,Podman高频操作如下。
◆搜索容器镜像
执行如下命令搜索容器,和Docker的操作十分类似,只是多了quay.io的容器镜像,和Docker不同的是,Podman没有守护进程,故使用前无需启动守护进程:
podman search ubuntu
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
quay.io quay.io/ratpoison/oregano-test-ubuntu 0
quay.io quay.io/tamr/ubuntu 0
quay.io quay.io/refgenomics/docker-ubuntu Base Ubuntu image + Python 0
quay.io quay.io/spearow/machine-learning-container-ubuntu-native 0
quay.io quay.io/spearow/machine-learning-container-ubuntu-opencl 0
quay.io quay.io/widen/ubuntu # Ubuntu Docker base images [![Docker Repos... 0
quay.io quay.io/cybozu/ubuntu Cybozu's base ubuntu container that extends ... 0
quay.io quay.io/cybozu/ubuntu-debug Ubuntu image extending quay.io/cybozu/ubuntu... 0
quay.io quay.io/rwce/ubuntu 0
quay.io quay.io/sameersbn/ubuntu 0
quay.io quay.io/fubar/ubuntu-indexer Container for running DXR indexing jobs. 0
quay.io quay.io/aptible/ubuntu (https://quay.io/repository/aptible/ubunt... 0
quay.io quay.io/nabinno/dove-ubuntu-dotfiles 0
quay.io quay.io/redsift/buildos-ubuntu 0
quay.io quay.io/libvirt/buildenv-libvirt-ubuntu-18 0
quay.io quay.io/charter-os/ubuntu-source-base 0
quay.io quay.io/charter-os/ubuntu-source-openstack-base 0
quay.io quay.io/picmonkey/ubuntu-go 0
quay.io quay.io/charter-os/ubuntu-source-keystone 0
quay.io quay.io/argo-testing/ubuntu 0
quay.io quay.io/charter-os/ubuntu-source-barbican-keystone-listener 0
quay.io quay.io/nordstrom/baseimage-ubuntu Nordstrom Ubuntu container baseimage. 0
quay.io quay.io/charter-os/ubuntu-source-keystone-base 0
quay.io quay.io/charter-os/ubuntu-source-keystone-fernet 0
quay.io quay.io/charter-os/ubuntu-source-barbican-base 0
docker.io docker.io/library/ubuntu Ubuntu is a Debian-based Linux operating sys... 10076 [OK]
docker.io docker.io/library/ubuntu-debootstrap debootstrap --variant=minbase --components=m... 40 [OK]
docker.io docker.io/library/ubuntu-upstart Upstart is an event-based replacement for th... 100 [OK]
docker.io docker.io/rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi... 231 [OK]
docker.io docker.io/1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK]
docker.io docker.io/pivotaldata/ubuntu-gpdb-dev Ubuntu images for GPDB development 0
docker.io docker.io/1and1internet/ubuntu-16-nginx-php-phpmyadmin-mariadb-10 ubuntu-16-nginx-php-phpmyadmin-mariadb-10 11 [OK]
docker.io docker.io/1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0 13 [OK]
docker.io docker.io/dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface ... 358 [OK]
docker.io docker.io/pivotaldata/ubuntu A quick freshening-up of the base Ubuntu doc... 2
docker.io docker.io/smartentry/ubuntu ubuntu with smartentry 1 [OK]
docker.io docker.io/1and1internet/ubuntu-16-nginx-php-5.6-wordpress-4 ubuntu-16-nginx-php-5.6-wordpress-4 7 [OK]
docker.io docker.io/1and1internet/ubuntu-16-apache-php-5.6 ubuntu-16-apache-php-5.6 14 [OK]
docker.io docker.io/consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session... 190 [OK]
docker.io docker.io/i386/ubuntu Ubuntu is a Debian-based Linux operating sys... 18
docker.io docker.io/1and1internet/ubuntu-16-php-7.1 ubuntu-16-php-7.1 1 [OK]
docker.io docker.io/1and1internet/ubuntu-16-nginx-php-7.0 ubuntu-16-nginx-php-7.0 4 [OK]
docker.io docker.io/1and1internet/ubuntu-16-sshd ubuntu-16-sshd 1 [OK]
docker.io docker.io/1and1internet/ubuntu-16-nginx-php-5.6 ubuntu-16-nginx-php-5.6 8 [OK]
docker.io docker.io/1and1internet/ubuntu-16-apache-php-7.1 ubuntu-16-apache-php-7.1 6 [OK]
docker.io docker.io/ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 98 [OK]
docker.io docker.io/nuagebec/ubuntu Simple always updated Ubuntu docker images w... 24 [OK]
docker.io docker.io/eclipse/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, ... 11 [OK]
docker.io docker.io/darksheer/ubuntu Base Ubuntu Image -- Updated hourly 5 [OK]
docker.io docker.io/1and1internet/ubuntu-16-rspec ubuntu-16-rspec 0 [OK]
◆拉取镜像
运行如下命令从docker.io镜像仓库拉取所需容器镜像:
podman pull docker.io/library/ubuntu
Trying to pull docker.io/library/ubuntu...Getting image source signatures
Copying blob 22e816666fd6: 0 B / 25.45 MiB [-----------------------------------]
Copying blob 22e816666fd6: 0 B / 25.45 MiB [-----------------------------------]
Skipping blob 22e816666fd6 (already present): 25.45 MiB / 25.45 MiB [=======] 2s
Copying blob 079b6d2a1e53: 0 B / 34.54 KiB [-----------------------------------]
Skipping blob 22e816666fd6 (already present): 25.45 MiB / 25.45 MiB [=======] 2s
Skipping blob 079b6d2a1e53 (already present): 34.54 KiB / 34.54 KiB [=======] 2s
Skipping blob 11048ebae908 (already present): 849 B / 849 B [===============] 2s
Skipping blob c58094023a2e (already present): 162 B / 162 B [===============] 2s
Copying config cf0f3ca922e0: 3.33 KiB / 3.33 KiB [==========================] 0s
Writing manifest to image destination
Storing signatures
cf0f3ca922e08045795f67138b394c7287fbc0f4842ee39244a1a1aaca8c5e1c
或从quay.io镜像仓库拉取Ubuntu镜像,具体操作如下:
podman pull quay.io/nordstrom/baseimage-ubuntu
Trying to pull quay.io/nordstrom/baseimage-ubuntu...Getting image source signatures
Copying blob 9dc28067479e: 0 B / ? [------------------------------------------=]
Copying blob 2f93236311d4: 0 B / ? [------------------------------------------=]
Copying blob 674d470597e3: 0 B / ? [------------------------------------------=]
Copying blob 616c777d0c1c: 0 B / ? [------------------------------------------=]
Copying blob 787cd08ca56c: 0 B / ? [------------------------------------------=]
Copying blob a3ed95caeb02: 0 B / ? [------------------------------------------=]
Copying blob 9dc28067479e: 286.58 KiB / ? [------------------=----------------]
Copying blob 9dc28067479e: 525.58 KiB / ? [----------=------------------------]
Copying blob 2f93236311d4: 846 B / ? [---------------------------=---------] 1s
Copying blob 9dc28067479e: 722.58 KiB / ? [--------------------------=--------]
Copying blob 9dc28067479e: 962.58 KiB / ? [--=--------------------------------]
Copying blob 9dc28067479e: 1.05 MiB / ? [------------------------------=------]
Copying blob 9dc28067479e: 1.14 MiB / ? [--=----------------------------------] s
Copying blob 9dc28067479e: 1.22 MiB / ? [----------=--------------------------] s
Copying blob 9dc28067479e: 4.58 MiB / ? [------------=------------------------]
Copying blob 9dc28067479e: 26.69 MiB / ? [-------------------------------=----] s
Copying blob 9dc28067479e: 27.41 MiB / ? [--------------------=---------------] s
Copying blob 9dc28067479e: 34.24 MiB / ? [--------=---------------------------] s
Copying blob 9dc28067479e: 34.27 MiB / ? [----=-------------------------] 2m18s s
Copying blob 2f93236311d4: 846 B / ? [----------------------------=-----] 2m18s s
Copying blob 674d470597e3: 398 B / ? [---------------------=------------] 2m18s s
Copying blob 616c777d0c1c: 850 B / ? [------------------------=---------] 2m18s s
Copying blob 787cd08ca56c: 163 B / ? [-----------=----------------------] 2m18s s
Copying blob a3ed95caeb02: 32 B / ? [---=-------------------------------] 2m18s s
Skipping blob a3ed95caeb02 (already present): -1 B / ? [-----------------=] 2m18s
Copying blob 3aa9aed5adc5: 289 B / ? [-------------------------=--------] 2m18s
Copying blob 68ff0e097be7: 29.27 MiB / ? [---------------=--------------] 2m18s
Copying blob 6537b4adcf0a: 155 B / ? [-------------------=--------------] 2m18s
Copying blob 4f5db9ac9423: 204.06 KiB / ? [----------------------=------] 2m18s
Copying blob 510e3d77686a: 306 B / ? [--------=-------------------------] 2m18s
Copying blob 7b4c0a80c573: 27.88 MiB / ? [----=-------------------------] 2m18s
Copying blob 892974601607: 4.93 MiB / ? [-------------=-----------------] 2m18s
Copying blob 5605a98a238b: 425 B / ? [-----------------------------=----] 2m18s
Copying blob 9cbb8b76253e: 8.18 KiB / ? [------=------------------------] 2m18s
Copying blob 3fe967ada79a: 150 B / ? [------------------------=---------] 2m18s
Copying blob 4d791d869d71: 3.48 KiB / ? [-----------------------=-------] 2m18s
Writing manifest to image destination
Storing signatures
28603889d5d8a37259a6ae0b9d5c9bc8933844fdf0171b96f4ed86387f02c8ba
◆查看本地镜像
执行如下命令查看本地镜像:
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/ubuntu latest cf0f3ca922e0 13 days ago 66.6 MB
quay.io/nordstrom/baseimage-ubuntu latest 28603889d5d8 21 months ago 185 MB
◆运行Podman容器
运行如下命令运行Podman容器
podman run -itd -p 220:22 --name ubuntu ubuntu /bin/bash
908d64e3028fbac5051ba70258e3355c9224a5afd8ee6567c8c8cc37ff430995
或:
podman run -itd -p 222:22 --name ubuntu1804 baseimage-ubuntu /bin/bash
56306b158f4fc8e038fe331df164a63625a7b07a5f437fd1ded93a6f44885ef3
成功运行后,运行如下命令查看:
podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcb99f84aff7 quay.io/nordstrom/baseimage-ubuntu:latest /bin/bash 5 seconds ago Up 5 seconds ago 0.0.0.0:222->22/tcp ubuntu1804
b2e19e9c51ee docker.io/library/ubuntu:latest /bin/bash About a minute ago Up About a minute ago 0.0.0.0:220->22/tcp ubuntu
◆进入容器进行操作
如要进入容器进行各种操作,可以使用如下命令:
podman exec -it bcb99f84aff7 /bin/bash
root@bcb99f84aff7:/# cat /etc/issue
Ubuntu Bionic Beaver (development branch) \n \l
或:
podman exec -it b2e19e9c51ee /bin/bash
root@b2e19e9c51ee:/# cat /etc/issue
Ubuntu 18.04.3 LTS \n \l
◆SSH远程登录容器进行操作
Podman可以创建并启动一个容器以后台方式运行,这是比较普遍的容器运行方式,关键操作如下:
podman run -d -t -p 2222:22 --name ubuntu1804lts ubuntu /usr/bin/top
800c3586441d4cea218016b6e99b9198aa505393130cc94144a5778515b162fc
上述命令中,-d参数是detach(分离)的缩写,表示容器以后台进程形式运行并显示其容器ID,-t参数表示分配一个终端给top命令,-p参数进行端口映射,即将主机(127.0.0.1)的端口2222映射到容器的端口22,这样访问主机中的2222端口就等于访问容器中的22端口。,--name指定容器名称,容器成功创建运行后,可以运行如下命令查看:
podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
800c3586441d docker.io/library/ubuntu:latest /usr/bin/top 32 seconds ago Up 32 seconds ago 0.0.0.0:2222->22/tcp ubuntu1804lts
...
可以从PORTS列看到端口映射,从NAMS列看到容器名称,STATUS列找到容器运行状态,Up表示容器正在运行。PORTS列可以看到端口映射,Podman是调用了iptables实现的端口映射,需要特别注意的是,要让容器在后台一直运行,必须要有一个前台持续执行的进程,否则将会自动退出。此外要直接进入容器进行操作有多种方法,最基本的就是attach到容器了,关键操作如下:
podman attach 800c3586441d
这样就可以看到以后台模式运行的top命令了,快捷键Ctrl+C退出容器,不过这不是最终目标,最终目标是要实现SSH连接,犹如操作服务器一般,需在Ubuntu server命令行执行如下命令:
podman exec -t -i 800c3586441d /bin/bash #在同一容器中执行bash才可以运行安装配置命令
-t和-i参数常常连用,分别是tty(终端)和interactive(交互)的缩写,表示分配一个为终端并进入交互模式,在容器中,执行如下命令安装和配置SSH服务,关键操作如下:
root@800c3586441d:/# passwd root
root@800c3586441d:/# apt-get update
root@800c3586441d:/# apt-get install net-tools ssh vim -y
随后还需对SSH服务进行配置,取消默认配置对root用户登录的限制,具体操作如下:
root@800c3586441d:/# vim /etc/ssh/sshd_config
...
PermitRootLogin yes #取消井号注释,并将值修改为yes,即允许root通过SSH服务登录
...
保存退出后启动SSH服务,执行如下命令:
root@800c3586441d:/# service ssh start
* Starting OpenBSD Secure Shell server sshd [ OK ]
最后在系统中使用如下命令及刚刚设置的密码,通过SSH登录到容器实例中:
ssh root@127.0.0.1 -p 2222 #SSH登录容器
输入密码即可通过SSH登录到该容器。
◆获得所有运行的容器信息
执行如下命令查看所运行的容器:
podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf8eadd43bb6 docker.io/library/ubuntu:latest /usr/bin/top 5 minutes ago Up 5 minutes ago 0.0.0.0:2222->22/tcp ubuntu1804lts
bcb99f84aff7 quay.io/nordstrom/baseimage-ubuntu:latest /bin/bash 13 minutes ago Up 13 minutes ago 0.0.0.0:222->22/tcp ubuntu1804
b2e19e9c51ee docker.io/library/ubuntu:latest /bin/bash 14 minutes ago Up 14 minutes ago 0.0.0.0:220->22/tcp ubuntu
此命令可以显示所有容器,包括已经停止的容器。
◆获得所运行容器的日志
要查看容器的运行日志,可以使用如下命令:
podman logs --latest
=> sourcing 20-copy-config.sh ...
=> sourcing 40-ssl-certs.sh ...
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.2. Set the 'ServerName' directive globally to suppress this message
[Sat Oct 26 15:11:13.608488 2019] [ssl:warn] [pid 1:tid 140482731112704] AH01909: 10.88.0.2:8443:0 server certificate does NOT include an ID which matches the server name
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.2. Set the 'ServerName' directive globally to suppress this message
[Sat Oct 26 15:11:13.672450 2019] [ssl:warn] [pid 1:tid 140482731112704] AH01909: 10.88.0.2:8443:0 server certificate does NOT include an ID which matches the server name
[Sat Oct 26 15:11:13.672548 2019] [lbmethod_heartbeat:notice] [pid 1:tid 140482731112704] AH02282: No slotmem from mod_heartmonitor
[Sat Oct 26 15:11:13.674932 2019] [mpm_event:notice] [pid 1:tid 140482731112704] AH00489: Apache/2.4.33 (Fedora) OpenSSL/1.1.0h-fips configured -- resuming normal operations
[Sat Oct 26 15:11:13.674976 2019] [core:notice] [pid 1:tid 140482731112704] AH00094: Command line: 'httpd -D FOREGROUND'
192.168.1.15 - - [26/Oct/2019:15:14:33 +0000] "GET / HTTP/1.1" 403 4650 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
[Sat Oct 26 15:14:33.783717 2019] [autoindex:error] [pid 30:tid 140482072016640] [client 192.168.1.15:58876] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
192.168.1.15 - - [26/Oct/2019:15:14:33 +0000] "GET /icons/apache_pb2.gif HTTP/1.1" 200 4234 "http://192.168.1.168:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
192.168.1.15 - - [26/Oct/2019:15:14:33 +0000] "GET /icons/poweredby.png HTTP/1.1" 200 2616 "http://192.168.1.168:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
192.168.1.15 - - [26/Oct/2019:15:14:34 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "http://192.168.1.168:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
◆停止容器
如需停止某个容器,可以执行如下命令:
podman stop ubuntu #容器ID最为精准
◆删除一个容器
删除一个容器,可以使用下列命令:
podman rm ubuntu #容器ID最为精准
先停止容器,然后才可以彻底删除,需要再次提醒大家的是,极力推荐大家使用普通用户身份运行Podman,令操作更加安全可靠。
Tips:Podman有哪些相关工具?
除了Podman容器管理工具之外,还有两个重要帮手,它们就是Buildah和Skopeo工具。
◆Buildah工具
Buildah构建OCI镜像的专用工具,可以使用Dockerfile中的所有命令,并可无需超级用户权限构建Dockerfiles镜像,尽管Podman也能构建Docker镜像,但速度很慢。
◆Skopeo工具
Skopeo是一个镜像处理工具,用来专门管理镜像仓库,可轻松通过push,pull和复制镜像来处理Docker及OCI镜像。
这样,Podman ,Buildah和Skopeo这三个工具组合在一起,就实现了一套完整的容器管理工具组合,需要提醒大家的是,Podman兼容Docker容器的,但还支持更多的镜像仓库。
15.3 CentOS 7虚拟机中安装Docker-ce
目前通过KVM运行CentOS 7使用Docker,应该是最为稳妥的方法了,方法如下。
1.安装Docker
CentOS 7中安装Docker的方法如下。
◆下载安装官方Docker CE Stable软件仓库
运行如下命令下载官方软件仓库:
curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
◆安装社区版
运行如下命令进行安装:
yum install docker-ce -y
◆启动docker
执行如下命令启用启动Docker服务:
systemctl enable docker
systemctl start docker
运行Docker服务后,如果使用第一种方法安装的,将会看到两条警告:
systemctl status docker
及:
docker version
Client: Docker Engine - Community
Version: 19.03.4
API version: 1.40
Go version: go1.12.10
Git commit: 9013bf583a
Built: Fri Oct 18 15:52:22 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.4
API version: 1.40 (minimum version 1.12)
Go version: go1.12.10
Git commit: 9013bf583a
Built: Fri Oct 18 15:50:54 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.6
GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version: 1.0.0-rc8
GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version: 0.18.0
GitCommit: fec3683
15.4. Docker和虚拟化技术的异同
Docker是一种典型的容器技术,类似于FreeBSD上的Jail,每一个容器实际上就是系统中一个沙箱,内核级别的隔离应用程序,而主流的完全虚拟化技术,如Red Hat KVM或VMware ESXi的Hypervisor 则是虚拟出一个完整计算机硬件体系,物理计算机有的硬件全部使用软件虚拟实现,打一个类似的比喻,把KVM或VMware的虚拟化技术比喻成一个施工队,它们的任务是在计算机内存中从打地基开始盖高楼,建大厦,而Docker则不这么干,它只会租一层现成的楼做办公室,然后将这层楼隔成多个较小的,独立的办公室,每个办公室都有相对独立,安全和安静的空间。租借办公室肯定要比从头开始盖楼更加高效和节省资源,而且因为Docker容器的存在,系统资源的使用可以更加精细化,有效减少应用程序间的资源竞争;安全方面也增强了很多,即使不幸被***攻破,破坏也只是在此容器之中而不会影响系统中其他容器。以Docker为代表的轻量级容器技术的角度来审视完全虚拟化技术,虚拟机系统既浪费资源又难以管理,更重要的是还不安全,图15-3和图15-4是虚拟化技术和容器技术的对比,帮助大家加深理解。
图15-3 容器技术(图片来源:https://docs.docker.com/)
图15-4 基于Hypervisor的虚拟机技术(图片来源:https://docs.docker.com/)
深入到底层技术而言,虚拟化技术是通过Hypervisor实现虚拟化,而以Docker为代表的容器 技术则是一种内核隔离的技术,后者则更加快速和节约资源,简化配置,标准化发布,更为重要的是,在云技术大行其道的今天,主流云基础架构几乎都支持Docker,Google,微软以及Amazon等云端巨头相继推出相应的容器产品,云端Docker技术也风景独好,安全高效新天地。
说了这么多,很多读者可能会问,Docker是不是将会取代目前的虚拟化技术,容器会一统天下,其实容器技术和传统的虚拟化技术不是谁取代谁的问题,容器技术在一定程度上弥补了虚拟化技术的劣势,但却无法取代,二者是互补关系,这两种技术的融合要远大于竞争,如何将二者融合才是大家应该关注的问题,下面就来深入认识和理解Docker。
15.5.深入理解Docker并让Docker为我们工作
Docker本身由很多组件构成,Docker的组织架构如图15-5所示。
图15-5 Docker Engine的架构(图片来源:https://docs.docker.com/)
虽然Docker技术有一点点庞杂,但Docker应用起来并不复杂,Docker最关键的三大组件是镜像,仓库和容器,应用Docker需要从上述三个组件入手,首先是Docker镜像(Docker images),所谓镜像其实就是一个只读模板,这个模板除了可以通过Docker容器运行一个操作系统之外,还可以在其之上构建多个应用层Layer,例如可以使用Apache或Nginx构建Web server层,再加上其老搭档PHP构成应用处理层,最后构建Wordpress层,并把这些Layer整合到容器中,即可测试使用。打个形象的比喻,这些操作与在系统中构建LAMP stack十分类似,需要注意的是,所有这些应用层是可以重复使用的,而LAMP则不能,使用Docker可以减少许多重复劳动,从很大程度上提高了工作效率。
有了这些十分基础的images和layers,就可以轻松构建自己的Docker应用,事实上,网上已经要大量的现成的Docker镜像仓库供大家选择使用,这些仓库类似于Homwbrew或MacPort的软件仓库,被称之为公有镜像仓库,通过docker push 和docker pull命令分享和获取它们。
而镜像仓库(Docker Registry)有点像代码托管网站GitHub,不同的是托管Docker镜像而非源代码,也需要注册一个账号,登录后可以单击Explore Repositories选项进入Docker镜像仓库,选择自己需要的镜像,该镜像仓库已经足够大,满足日常要求没有问题。此外也可以将自己的镜像托管到Docker Hub上,便于自己或其他人使用。
从Docker Hub下载了现成的Docker镜像,就可以通过镜像来创建并运行Docker容器实例了,Docker容器运行起来后类似一部Linux虚拟机,只不过功能和系统资源消耗都比虚拟机小得多,容器有自己的虚拟网络系统,可以通过虚拟网络与外界通信和连接,总之用户可以像使用和管理Linux虚拟机一样管理和使用Docker容器。
此外,Docker还可以创建本地的私有镜像仓库,类似Ubuntu自己创建一个软件仓库,由于在本地,所以使用起来既方便又安全,下面将专门的章节介绍私有仓库的创建和配置,故此处不做展开。
简而言之,Docker使用起来很简单,就三个组件:镜像-仓库-容器,应用容器也就很简单了,就从这三部分入手,从Docker镜像仓库获得所需镜像,然后通过Docker镜像创建Docker容器,最后运行即可使用。熟悉了Dicker的三大组件,要想全面系统地认识Docker,还需对Docker本身深入探索。
Docker三大组件中,对于使用者而言,最为重要的就是镜像了,又称为基础镜像(Basic Image),因为Dokcker运转的核心是Docker镜像,Docker镜像安装好就是Ready状态了,开箱即用,只需基于Docker镜像就可以运行容器,而Docker镜像是由多层镜像构成,犹如一个三明治一般,多个层次之间通过AUFS这种文件系统整合到一起,Docker层叠的镜像结构如图15-6所示。
图15-6 Docker层叠的镜像结构
需要注意的是,只有处于Docker镜像顶层的Container Layer才支持完全的读写操作,其下诸层只能读。
AUFS(Advanced UnionFS)其实是一种Union File System(UnionFS),最新版本为4,而UnionFS简而言之就是可叠加的联合文件系统,把不同物理位置的目录挂载并集中到同一个目录中,联合多个目录而同时独立地保持它们的数据,并允许在目录中修改和删除不使用的目录,Ubuntu默认就采用AUFS作为Docker存储驱动程序。AUFS是由日本开发者Junjiro Okajima(岡島順治郎)2006年开发的一个开源项目,由于代码可读性差,没有注释而被Linus拒之门外,无法进入Linux内核,实在遗憾,不过Ubuntu一致在大力支持AUFS,此外,即使没有进入内核也没关系,还有Device Mapper技术。
大家对Device Mapper技术不会陌生,因为多数与存储相关的技术都是它来实现的,如LVM(逻辑卷管理),Soft RAID(软RAID)以及Multi Path(多路径)等技术。Device Mapper本质上就是一个开放框架,Kernel通过各种的Target Driver实现对I/O请求的过滤或重定向等操作,上述软 RAID,LVM和Multipath等实质就是一个Target Driver,其中一个名为Thin Provisioning Snapshot的Target Driver,就是Docker使用DeviceMapper中实现类似AUFS分层镜像的关键,Docker就是通过Thin Provisioning的快照功能构建多层的快照(snapshot)同样可以实现UnionFS那样的分层镜像,RHEL/CentOS默认就采用此方式,只不过Device Mapper的效率要比AUFS差很多,这也是为什么Docker在Ubuntu server上的表现要比RHEL/CentOS好得多的原因。
也许有人会问,开源世界那么多文件系统,为什么Docker镜像偏偏要采用这种分层的文件结构呢?其实分层文件系统最大好处就是资源充分共享,如多个镜像都从相同的基础镜像构建而来,那么Docker容器只需保存一份基础镜像,同时内存中也只需加载一份基础镜像,就可以为所有容器服务了,不仅如此,镜像的每一层都可以被共享。
概况而言,Cgroups限制了Docker运行时能够拥有的资源,而Namespces确保Docker容器内的进程看不到也影响不到外部的进程,上述这些概念可能有些复杂,不过不用着急,本章会循序渐进地帮助大家理解并通过大量实例来让大家顺利地掌握Docker容器技术。
简而言之,让Docker工作并不复杂,只需搜索并选择合适的Docker镜像,然后pull下来并基于该镜像创建和运行容器即可。
15.5.1.搜素Docker镜像
在前面的章节Docker应用关键中已经提到过,没有Docker镜像,Docker什么也干不了,幸运的是,Docker默认有Docker Hub这个镜像仓库可用。
Docker Hub是Docker官方维护的一个公共Docker镜像仓库 ,功能类似于Ubuntu官方的软件仓库,其中已经包括了数以万计的Docker镜像,对于大多数用户而言,通过在Docker Hub中搜索及下载现成的Docker镜像是最便捷和高效的方法了。
先来小试一下牛刀,可以使用如下命令来搜索常用镜像,如Ubuntu:
docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 9971 [OK]
dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 345 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 231 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 187 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 99 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 97 [OK]
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK]
ubuntu-debootstrap debootstrap --variant=minbase --components=m… 40 [OK]
nuagebec/ubuntu Simple always updated Ubuntu docker images w… 24 [OK]
i386/ubuntu Ubuntu is a Debian-based Linux operating sys… 18
1and1internet/ubuntu-16-apache-php-5.6 ubuntu-16-apache-php-5.6 14 [OK]
1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0 13 [OK]
ppc64le/ubuntu Ubuntu is a Debian-based Linux operating sys… 13
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mariadb-10 ubuntu-16-nginx-php-phpmyadmin-mariadb-10 11 [OK]
eclipse/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, … 11 [OK]
1and1internet/ubuntu-16-nginx-php-5.6 ubuntu-16-nginx-php-5.6 8 [OK]
1and1internet/ubuntu-16-nginx-php-5.6-wordpress-4 ubuntu-16-nginx-php-5.6-wordpress-4 7 [OK]
1and1internet/ubuntu-16-apache-php-7.1 ubuntu-16-apache-php-7.1 6 [OK]
darksheer/ubuntu Base Ubuntu Image -- Updated hourly 5 [OK]
1and1internet/ubuntu-16-nginx-php-7.0 ubuntu-16-nginx-php-7.0 4 [OK]
pivotaldata/ubuntu A quick freshening-up of the base Ubuntu doc… 2
1and1internet/ubuntu-16-sshd ubuntu-16-sshd 1 [OK]
smartentry/ubuntu ubuntu with smartentry 1 [OK]
1and1internet/ubuntu-16-php-7.1 ubuntu-16-php-7.1 1 [OK]
pivotaldata/ubuntu-gpdb-dev Ubuntu images for GPDB development 0
Docker hub中居然有如此丰富的系统镜像,镜像选择的参考标准是Star数多的和尽量选择官方推出的Docker镜像,根据此标准,此处选择第一个Docker镜像。
15.5.2.获取Docker镜像
从Docker的镜像库中一下子搜索出很多的Ubuntu镜像,一般来说需要先在Reference server上测试以保证安全和稳定,尤其是生产环境使用。选择一个要安装的版本就可以精准的安装了,这里选择Ubuntu官方Docker镜像,因为该镜像完全符合上述选择标准,要获得上述Docker镜像可以使用docker pull命令来从Docker Hub在线仓库获取所需要的镜像,使用如下命令安装即可:
docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
75c416ea735c: Pull complete
c6ff40b6d658: Pull complete
a7050fc1f338: Pull complete
f0ffb5cf6ba9: Pull complete
be232718519c: Pull complete
Digest: sha256:a0ee7647e24c8494f1cf6b94f1a3cd127f423268293c25d924fbe18fd82db5a4
Status: Downloaded newer image for ubuntu:latest
在pull镜像的过程中就可以看到前面提到的Layer概念,每一个Layer对应一个条目,下载完成就显示下载完毕,而正在下载的Layer就显示正在Pulling或Downloading,完成当前层的下载就显示Pull complete,所有层都下载完成后,Docker镜像也就下载完毕,然后解压,无论下载还是解压,都有进度条显示,这些可以加深对Docker镜像结构的理解。需要注意的是,如果本地找不到镜像的话, Docker将会自动下载镜像hello-world:latest。
成功安装指定镜像后,运行以下命令,可以看到本地多出如下几个系统镜像:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 2ca708c1c9cc 4 days ago 64.2MB
看到上述结果,说明ubuntu镜像下载安装成功,选择不同的第三方制作镜像,会有不同安装结果,大家可以根据自己的需求来选择和安装。所返回的结果中,含有很多非常有价值的信息,如仓库名称(REPOSITORY)和标签名称(TAG),它们常常一起使用,可以写为ubuntu:latest,用来标记容器,latest是默认的标签,从镜像创建日期(CREATED)可以了解镜像的新旧,至于镜像大小(SIZE)是指解压后的大小,ubuntu镜像下载大小其实仅为几十兆而已。最后,成功下载了Docker镜像,就可以通过镜像创建并启动容器了。
15.5.3. 创建镜像并以后台方式运行容器
Docker以刚才所下载的镜像为基础创建启动容器的,创建并启动一个容器以后台方式运行,这是比较普遍的容器运行方式,关键操作如下:
docker run -d -t -p 2222:22 --name ubuntu1804 ubuntu /usr/bin/top
800c3586441d685d439bc1d2e52db508a54c386ed5099062d364f7224b65c947
上述命令中,-d参数是detach(分离)的缩写,表示容器以后台进程形式运行并显示其容器ID,-t参数表示分配一个终端给top命令,-p参数进行端口映射,即将主机(127.0.0.1)的端口2222映射到容器的端口22,这样访问主机中的2222端口就等于访问容器中的22端口。,--name指定容器名称,容器成功创建运行后,可以运行如下命令查看:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
800c3586441d ubuntu "/usr/bin/top" 44 seconds ago Up 43 seconds 0.0.0.0:2222->22/tcp ubuntu1804
可以从PORTS列看到端口映射,从NAMS列看到容器名称,STATUS列找到容器运行状态,Up表示容器正在运行。PORTS列可以看到端口映射,Dockers是调用了iptables实现的端口映射,需要特别注意的是,要让Docker容器在后台一直运行,必须要有一个前台持续执行的进程,否则将会自动退出。再尝试使用端口映射和SSH服务连接到容器,具体方法和使用SSH登录到Linux服务器类似,具体操作如下:
ssh root@127.0.0.1 -p 2222
ssh_exchange_identification: Connection closed by remote host
连接失败,由于此时容器还没有安装网络管理工具和SSH服务,所以无法登录,由于无法通过SSH服务连接到Docker,就只能直接进入Docker容器进行操作,进入容器系统的方法有多种方法,最基本的就是attach到容器了,关键操作如下:
docker attach 800c3586441d
这样就可以看到以后台模式运行的top命令了,快捷键Ctrl+C退出容器,不过这不是最终目标,最终目标是要实现SSH连接,犹如操作服务器一般,需在Ubuntu server命令行执行如下命令:
docker exec -t -i 800c3586441d /bin/bash #在同一容器中执行bash才可以运行安装配置命令
-t和-i参数常常连用,分别是tty(终端)和interactive(交互)的缩写,表示分配一个为终端并进入交互模式,在容器中,执行如下命令安装和配置SSH服务,关键操作如下:
root@800c3586441d:/# apt-get update
root@800c3586441d:/# apt-get install net-tools ssh vim -y
随后还需对SSH服务进行配置,取消默认配置对root用户登录的限制,具体操作如下:
root@800c3586441d:/# vim /etc/ssh/sshd_config
...
PermitRootLogin yes #取消井号注释,并将值修改为yes,即允许root通过SSH服务登录
...
保存退出后启动SSH服务,执行如下命令:
root@800c3586441d:/# service ssh start
* Starting OpenBSD Secure Shell server sshd [ OK ]
Tips:如何让一个没有前台输出的进程在Docker后台运行?
常常需要一个进程在后台一直运行,不过这个进程没有前台输出,如何让其在Docker后台运行呢?其实很简单,只要在执行命令时,添加一个前台运行程序tail命令即可,这样既可以令没有前台的进程在后台持续运行,又能即时输出日志文件,一箭双雕,参考命令行如下所示:
service ssh start && tail -f /var/log/alternatives.log
为root用户设置密码,具体操作如下:
root@800c3586441d:/# passwd root
root@800c3586441d:/# exit #退出当前容器
最后在系统中使用如下命令及刚刚设置的密码,通过SSH登录到Docker的实例中:
ssh root@127.0.0.1 -p 2222 #SSH登录容器
当然,创建一个普通用户进行SSH登录更为安全和稳妥,成功启动SSH服务后,运行如下命令即可:
docker exec -t -i 800c3586441d /bin/bash
root@800c3586441d:/# useradd -m ubuntu
root@800c3586441d:/# passwd ubuntu
root@800c3586441d:/# exit
成功创建普通用户ubuntu后,即可使用ssh登录:
ssh ubuntu@127.0.0.1 -p 2222
Tips:如何保存修改后的容器镜像?
上面为容器安装了SSH服务及相关工具,使用起来十分方便,如果将其保存起来呢?下次再次用到就不用从头开始安装配置了,这就要用到Docker镜像修改命令docker commit了,具体方法如下:
docker commit -m='Ubuntu with SSH' --author='Henry' 800c3586441d ubuntu/sshd
sha256:382a459ac40105492e91f8c0fea4e5c7321fd5f1913d47ca54f82cdc551e789e
看到一长串的SHA256编码,说明镜像已经成功提交,上述命令中,ubuntu为目标镜像仓库名称,sshd则为自定义镜像名称,用--author来指定镜像修改者,-m后跟提交信息,类似git,最后再用如下命令查看一下:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu/sshd latest 382a459ac401 31 seconds ago 266MB #因为安装了软件,故镜像变胖了不少
...
15.5.4.容器运行命令的两种方式
获得镜像,然后使用镜像,容器中的系统和应用终于跑起来了,除了上述十分常用的以后台方式运行的容器之外,还可以通过命令和交换方式对容器中的系统进行操作,这两种方式各有利弊,大家可以根据具体情况来选择,下面就以实例来掌握这两种重要的操作方式。
◆命令方式
Docker的行命令方式,创建容器并在容器中执行指定命令,执行完退出容器会话并将结果返回给用户,该方式一次性运行一个命令,具体实例如下:
docker run ubuntu apt-get update -y #Docker的命令模式不支持交互操作,所以必须添加-y参数
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:3 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [156 kB]
...
apt-get update命令执行完毕,立即退出Docker容器,但对容器的操作结果不会丢失,可以通过如下命令来证实:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f21c99a0d6dc ubuntu "apt-get update -y" 46 seconds ago Exited (0) 16 seconds ago admiring_goldberg
可以看出,运行apt-get update命令的容器已在16秒前退出了。对于已经存在的容器,可以使用如下命令来执行命令:
docker exec ubuntu1804 apt-get update -y #可以通过容器名也可以使用容器ID来唯一标识一个容器
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
...
◆交互方式
在Docker的交互命令方式下,使用起来犹如在虚拟机的终端一样,对于不存在的容器,可以运行如下命令直接创建并进入交互模式,具体操作如下:
docker run -it --name us1804 ubuntu /bin/bash #容器名称为us1804,而该容器所采用的镜像为ubuntu
root@60b5eb206e1a:/# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.2 LTS"
root@60b5eb206e1a:/#
对于存在的容器而言,可以使用如下命令进入交换模式,下面就以容器ubuntu1804为例,进入该容器的交互模式:
docker exec -it ubuntu1804 /bin/bash #可以通过容器名也可以使用容器ID来唯一标识一个容器
上述命令中,-t参数让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,而-i参数则让容器的标准输入保持打开。最后出现提示符“root@XXXXXXXXXXXX:/#”就是容器系统的超级用户提示符,表示已经进入了Docker容器内的系统,XXXXXXXXXXXX表示容器的ID,如要退出Docker的容器系统,只需使用exit命令或组合键“Ctrl+d”即可退出,回到Ubuntu server系统。在交换方式中,还可以执行容器中所有的命令行,执行方法和在系统中几乎没有什么区别。比较而言,交换方式似乎更像是在使用Linux系统也更方便,这两种方式可以根据应用场景灵活选择。
Tips:docker run和docker exec命令的区别是什么?
docker run和docker exec是两个docker高频命令,它们的应用场景存在很大的区别,区别在于docker run命令通常是在新创建的容器中所使用的命令,即在没有其他容器运行的情况下,创建容器并启动它,可以只运行一个命令,也可以交互运行一组命令,而docker exec则是用于存在的某个容器中执行命令,即对一个存在且正在运行的容器进行各种操作,如配置或运行命令等。
15.5.5.Docker高频操作
活学活用Docker,必须掌握Docker的高频操作。
◆查看Docker版本信息
docker --version #仅查看客户端的docker版本
◆查看Docker配置信息
docker info
◆查看容器中正在运行的进程信息
执行下列命令显示一个容器中正在运行的进程信息:
docker top 800c3586441d
PID USER TIME COMMAND
2590 root 0:00 /usr/bin/top
6671 root 0:00 /usr/sbin/sshd
◆查看查看指定容器状态
运行如下命令获得Docker的容器状态:
docker ps -a
然后获得要查看容器的ID,通过如下命令查看容器的状态:
docker ps -a
使用获得CONTAINER ID,运行如下命令获得容器详细信息:
docker inspect 800c3586441d
...
◆根据镜像创建一个容器
根据所下载镜像创建容器Docker容器主要有以下两种方式,创建一个容器但并不启动,可以使用如下命令:
docker create ubuntu
3175f2466580988648cc3190ddc99d34727d759d9db44d9092e316207bb51381
使用如下命令创建容器并运行该容器:
docker run -d -t ubuntu /bin/bash
最后可以运行查看命令找出这两种方式的不同:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
920cd7b8bbc0 ubuntu "/bin/bash" 35 seconds ago Up 33 seconds eager_chaplygin
3175f2466580 ubuntu "/bin/bash" About a minute ago Created suspicious_cocks
...
从上述结果可知,第一种方法仅是创建而已,其状态为Created,而第二种方法不仅创建了一个容器并且其状态为UP,表明其已在运行之中。
◆容器管理相关操作
容器相关操作主要有启动,停止,重启,暂停,恢复和终结容器,运行如下命令启动/停止/重启/暂停/恢复/终结Docker容器:
docker start/stop/restart/pause/unpause/kill CONTAINER_ID(容器ID或名称)
docker start 800c3586441d #启动容器
docker pause 800c3586441d #挂起容器
docker unpause 800c3586441d #恢复容器
docker kill 800c3586441d #强行终结容器,谨慎使用
◆查看容器相关命令
查看容器的状态是最常用的操作之一,首先是查看正在运行的容器,操作如下:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e09f888e037c ubuntu "/bin/bash" 41 minutes ago Up 41 minutes 0.0.0.0:2222->22/tcp ubuntu1604
还查看最近一次启动的容器,操作如下:
docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e09f888e037c ubuntu "/bin/bash" 36 minutes ago Up 36 minutes 0.0.0.0:2222->22/tcp ubuntu1604
如果要查看所有的容器,可以运行如下命令:
docker ps -a
在前面的部分其实已经多次使用过查看命令了。
◆复制容器中的文件到容器外
运行如下命令从容器中复制文件或目录到本地一个路径:
docker cp 4102872ef8bf:/bin/bash ./bash_in_container
◆备份与恢复本地镜像
将容器导出为export.tar,具体操作如下:
docker export 4102872ef8bf > export.tar
还可以使用如下命令将export.tar导入为容器镜像:
cat export.tar | docker import - ubuntu:sshd #仓库名和标签名均可根据实际情况修改,这里采用ubuntu:changed
docker images
还可以将容器另保存为save.tar,具体操作如下:
docker save ubuntu:sshd > save.tar
还可以使用如下命令将save.tar恢复为容器镜像:
docker load < save.tar
docker images
◆显示一个镜像的历史
无论对镜像做了什么操作,都可以通过如下命令显示镜像历史:
docker history ubuntu
◆查看Docker容器日志
容器可以使用如下命令查看日志:
docker logs -f 6a1fb6f9a117
...
Get:19 http://archive.ubuntu.com/ubuntu xenial-updates/multiverse amd64 Packages [16.8 kB]
Get:20 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages [4930 B]
Get:21 http://archive.ubuntu.com/ubuntu xenial-backports/universe amd64 Packages [6241 B]
Fetched 24.2 MB in 1min 28s (273 kB/s)
Reading package lists...
可以看到前面升级软件仓库列表的日志,此命令的效果类似tailf,随时将新出现的日志显示。
◆直接获得容器的IP地址
对Docker进行管理很多时候需要获得容器的IP地址,正常需要进入容器,然后再运行ifconfig获得,其实还可以更加高效地获得容器的IP地址,关键操作如下:
docker inspect -f '{{ .NetworkSettings.IPAddress }}' e09f888e037c
172.17.0.2
◆删除Docker容器
删除某个容器前,需要先停止这个容器,使用如下命令停止容器:
docker stop 800c3586441d
需要注意的是,处于运行状态的容器是无法直接删除的,否则报如下错误:
Error response from daemon: You cannot remove a running container 5390905e33a78746979aa13c4d45a562efedd1debff39a6791d83ff426bdbd0b. Stop the container before attempting removal or force remove
停止Docker容器后即可执行如下操作删除Docker容器:
docker rm 800c3586441d
此外,如果运行了很多容器,需要一次性全部停止及删除,可以使用如下名来实现:
docker stop `docker ps -qa` #一次停止所有的容器,需要注意的是此命令生产环境慎用
docker rm `docker ps -qa` #一次删除所有的容器,需要注意的是此命令生产环境慎用
◆删除本地Docker镜像
如果要删除本地的Docker镜像,可以使用docker rmi命令,关键操作如下:
docker rmi ubuntu
如果碰到个别无法删除的镜像,可以添加--force参数来强制删除。
需要注意的是,概念上要明确区分容器和镜像,这是两个完全不同的概念,前者类似于模板,后者则类似于实例,在操作上docker rmi用于删除镜像,而docker rm命令则是删除Docker容器,切记在删除某个镜像之前首先使用该命令删除依赖于这个Docker镜像的所有容器。
16.7.编辑修改Docker容器镜像
前面已经用到的编辑修改Docker镜像,可以说是定制Docker容器镜像是最高效便捷的方法,下面就以前面的Ubuntu/sshd镜像为例,为镜像安装Apache Web服务,最后再提交和保存,便于以后的使用。
登录到容器系统后在超级用户提示符下安装Apache2服务,操作如下:
docker run -t -i -p 80:80 ubuntu/sshd /bin/bash
root@8ea5e8dad03d:/#apt-get update
root@8ea5e8dad03d:/#apt-get install apache2 -y
成功后运行如下命令退出Docker:
root@8ea5e8dad03d:/#exit
至此,容器的超级管理员密码已经修改,但还需提交才能令修改生效,关键操作如下:
docker commit -m 'ubuntu with Apache' 8ea5e8dad03d ubuntu/httpd
sha256:50dc26eadc4463f41e2e17a2fbdba8e88b505419039583b5e2bf3037cdd3b063
上述操作中,docker commit命令的功能是从容器创建Docker镜像,-m参数指定提交的说明信息,,后面就是用于创建镜像容器的ID,末尾指定目标镜像的仓库名和标签(tag) 信息,创建成功后会返回这个镜像的ID信息,可运行如下命令获得镜像信息:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu/httpd latest 877738767036 31 seconds ago 317MB
ubuntu/sshd latest 977a4d0f76bd 16 minutes ago 264MB
ubuntu latest 47b19964fb50 3 weeks ago 88.1MB
成功修改ubuntu镜像后,就可以用新创建的镜像创建容器,关键操作如下:
docker run -idt -p 2222:22 -p 80:80 ubuntu/httpd /bin/bash
5118efb4b5af22b65064a3ff5c8b9eeafdae56fb377975cb6e36d9f911421e84
然后在新容器中启动Apache Web服务并安装文本界面浏览器elinks,方法如下:
root@5118efb4b5af:/# service apache2 start
root@5118efb4b5af:/# apt-get install elinks -y
root@5118efb4b5af:/# elinks 172.17.0.2
成功访问Apache后,即可看到熟悉的默认页面,这里只是简单地修改了Docker实例,其实还可以根据自己的需求,基于官方的各种Docker镜像,安装自己所需要的服务或开源程序,如MySQL,LDAP或Wordpress等,再提交为新镜像使用,这样使用Ubuntu就会很高效了,下面就以MySQL为例来定制一个容器,关键操作如下:
docker search ubuntu
这次选择Ubuntu官方镜像来定制自己的MySQL服务器,将其拉(Pull)到本地,操作如下:
docker pull ubuntu:latest
成功下载官方Ubuntu镜像后,运行如下命令查看:
docker images
ubuntu latest 47b19964fb50 12 days ago 88.1MB
...
以交互方式启动所下载镜像ubuntu,关键操作如下:
docker run -t -i ubuntu /bin/bash
root@fa3577cb7cfc:/#
登录到容器系统后,首先修改root用户密码,然后运行如下命令安装MySQL:
root@fa3577cb7cfc:/# passwd root
root@fa3577cb7cfc:/# apt-get update
root@fa3577cb7cfc:/# apt-get install -y mysql-server mysql-client ssh
成功安装MySQL后,运行如下命令提交令修改立即生效:
docker commit -m 'Ubuntu with MySQL' fa3577cb7cfc ubuntu/mysql
sha256:dff60c57a2f11b693b3973b7be77b02f230e749d88bd30464add875da7a3bf06
成功提交修改后的ubuntu镜像后,立即用新创建的镜像运行容器,关键操作如下:
docker run -idt -p 3306:3306 ubuntu/mysql /bin/bash
随后运行如下命令启动和登录数据库:
service mysql start
mysql -uroot -p
mysql> SELECT VERSION();
+----------------------------------+
| VERSION() |
+----------------------------------+
| 5.7.25-0ubuntu0.18.04.2 |
+-----------------------------------+
1 row in set (0.00 sec)
可以看到MySQL的版本说明Docker容器工作正常,定制成功。如果要同时打开多个端口,可参照如下命令:
docker run -d -p 2222:22 -p 80:80 -p 3306:3306 ubuntu:mysql
本章小结
至此,学习了Docker是一种什么技术后,搞清几个基本概念和术语,如Docker Engine,Docker Host,Docker compose,Docker Swarm和Kubernets等,掌握了Docker Engine的基本操作,如创建,查看和管理容器,Docker的高频操作和通过修改现成容器并提交保存,Docker容器就算是入了门。最后,还掌握了最新的Podman容器管理工具,熟悉其高频操作,需要特别注意的是,无论Docker还是Podman,都是一种内核级别的隔离技术,与主机系统共享内核,并通过Basic Image实现标准化的Linux执行环境,而非一种虚拟化技术,很多朋友都将Docker和虚拟化混为一谈,这是错误的。
EOF