Docker简介

什么是Docker?

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker能干嘛?

软件开发最大的麻烦事之一,就是环境配置。而Docker可以十分方便的配置它们。

传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

Docker的三个基本概念

Docker 包括三个基本概念:

  • 镜像(image):Docker 镜像(image),相当于是一个root文件系统。例如官方镜像 Ubuntu: 16.04 就包含了完整的一套 Ubuntu 16.04 最小系统的root文件系统。
  • 容器(Container):容器(Container) Docker 镜像(image)生成。一旦容器生成,就会同时存在两个文件: image 文件和容器文件。而且关闭容器并不会删除容器文件,只是容器停止运行而已。
  • 仓库(Repository):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

安装Docker

Docker 分为 stable testnightly 三个更新频道。

Get Docker | Docker Documentation

在Ubuntu安装Docker

Docker 支持以下版本的 Ubuntu 操作系统:

  • Ubuntu Hirsute 21.04
  • Ubuntu Groovy 20.10
  • Ubuntu Focal 20.04 (LTS)
  • Ubuntu Bionic 18.04 (LTS)

Docker 可以安装在 64 位的 x86 平台或 ARM 平台上。Ubuntu 发行版中,LTS(Long-Term-Support)长期支持版本,会获得 5 年的升级维护支持,这样的版本会更稳定,因此在生产环境中推荐使用 LTS 版本。

卸载旧版本Docker

旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本:

1
2
3
sudo apt-get remove docker \
docker-engine \
docker.io

使用 APT 安装

由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改。因此,我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书。

1
2
3
4
5
6
7
8
sudo apt-get udate

sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release

为了确认所下载软件包的合法性,需要添加软件源的 GPG 密钥。

1
2
3
4
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 官方源
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

sources.list中添加 Docker 软件源

1
2
3
4
5
6
7
8
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 官方源
# $ echo \
# "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
# $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安装 Docker

更新 apt 软件包缓存,并安装 docker-ce

1
2
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

启动 Docker

1
2
sudo systemctl enable docker
sudo systemctl start docker

建立 Docker 用户组

默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

建立docker组:

1
sudo groupadd docker

将当前用户加入docker组:

1
sudo usermod -aG docker $USER

在CentOS安装Docker

切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker

Docker 支持 64 位版本 CentOS 7/8,并且要求内核版本不低于 3.10。 CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存储层驱动)无法使用,并且部分功能可能不太稳定。

卸载旧版本Docker

旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本:

1
2
3
4
5
6
7
8
9
10
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

使用 yum 安装

安装依赖包:

1
sudo yum install -y yum-utils

添加yum软件源:

1
2
3
4
5
6
7
8
9
sudo yum-config-manager \
--add-repp \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

# 官方源
sudo yum-config-manager \
--add-repp
https://download.docker.com/linux/centos/docker-ce.repo

如需测试版本的Docker:

1
sudo yum-config-manager --enable docker-ce-test

安装 Docker

更新 yum 软件源缓存,并安装 docker-ce

1
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

CentOS8的额外设置

由于 CentOS8 防火墙使用了 nftables,但 Docker 尚未支持 nftables, 我们可以使用如下设置使用 iptables

更改 /etc/firewalld/firewalld.conf

1
2
# FirewallBackend=nftables
FirewallBackend=iptables

或执行以下命令:

1
2
firewall-cmd --permanent --zone=trusted --add-interface=docker0
firewall-cmd --reload

启动 Docker

1
2
sudo systemctl enable docker
sudo systemctl start docker

建立 Docker 用户组

默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。

建立 docker 组:

1
sudo groupadd docker

将当前用户加入docker组:

1
sudo usermod -aG docekr $USER

添加内核参数

如果在 CentOS 使用 Docker 看到下面的这些警告信息:

1
2
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

添加内核配置参数以启用这些功能

1
2
3
4
sudo tee -a /etc/sysctl.conf <<-EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

重新加载sysctl.conf即可

1
sudo sysctl -p

Docker食用指南

镜像使用指南

Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。

获取镜像

从 Docker 镜像仓库获取镜像的命令是 docker pull。命令格式是:

1
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

参数说明:

  • TAG:标签(版本)
  • DIGEST:摘要
  • OPTIONS:
    • -a :下载镜像仓库中所有的指定镜像;
    • –disable-content-trust:跳过镜像验证(默认值是true);
    • –platform: 如果服务具有多平台功能,则设置平台;
    • -q:一直详细输出;

具体选项可以通过docker pull --help命令查看。

例子如下:

1
2
3
4
5
6
7
8
$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
92dc2a97ff99: Pull complete
be13a9d27eb8: Pull complete
c8299583700a: Pull complete
Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04

上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub (docker.io)获取镜像。而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。docker pull 命令的输出结果最后一行给出了镜像的完整名称,即: docker.io/library/ubuntu:18.04

  • Docker 镜像仓库地址:地址的格式一般是域名/IP[:端口号]。默认地址是 Docker Hub(docker.io)。
  • 仓库名:仓库名是两段式名称,即<用户名>/<软件名>。对于 Docker Hub,如果没有指定用户名,则默认是library,也就是官方镜像。

运行

有了镜像后,可以以这个镜像为基础启动并运行一个容器。以上面的Ubuntu:18.04为例,如果打算启动里面的bash并且进行交互式操作的话,可以执行以下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker run -it --rm ubuntu:18:04 bash

# 以下是容器内操作
root@e7009c6ce357:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

docker run就是要运行容器的命令,这里简单说明一下上面用到的参数

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
  • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash

进入容器后就可以在 Shell 下操作执行任何所需的命令。例如,上面就执行了cat /etc/os-release,这是Linux常用的查看当前系统版本的命令,从返回的结果可以看到容器内是Ubuntu 18.04.1 LTS系统。

最后可以通过exit退出这个容器。

列出镜像

要想列出已经下载下来的镜像,可以使用 docker image ls 命令。

1
2
3
4
5
6
7
8
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183 MB
nginx latest 05a60462f8ba 5 days ago 181 MB
mongo 3.2 fe9198c04d62 5 days ago 342 MB
<none> <none> 00285df0df87 5 days ago 342 MB
ubuntu 18.04 329ed837d508 3 days ago 63.3MB
ubuntu bionic 329ed837d508 3 days ago 63.3MB

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签。因此,在上面的例子中,我们可以看到 ubuntu:18.04ubuntu:bionic 拥有相同的 ID,因为它们对应的是同一个镜像。

镜像体积

Docker Hub上显示的镜像体积是压缩后的体积大小,在镜像上传和下载的过程中镜像是保持压缩状态的。而使用命令docker image ls显示的是镜像下载到本地后展开的大小,准确说,是展开后的各层所占空间的总和。

另外一个需要注意的问题是,docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。相同的层只需要保存一份即可。

通过docker system df命令来查看镜像、容器、数据卷所占用的空间。

1
2
3
4
5
6
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 1 390.2MB 390.2MB (99%)
Containers 1 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 18 0 789B 789B

列出部分镜像

不加任何参数的情况下,docker image ls 会列出所有顶层镜像,但是有时候我们只希望列出部分镜像。docker image ls 有好几个参数可以帮助做到这个事情。

根据仓库名列出仓库

1
2
3
4
$ docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ba6acccedd29 23 months ago 72.8MB
ubuntu 18.04 5a214d77f5d7 23 months ago 63.1MB

列出特定的某个镜像,也就是说指定仓库名和标签

1
2
3
$ docker image ls ubuntu:18.04
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 5a214d77f5d7 23 months ago 63.1MB

删除本地镜像

如果要删除本地的镜像,可以使用 docker image rm 命令,其格式为:

1
$ docker image rm [选项] <镜像1> [<镜像2> ...]

其中,<镜像> 可以是 镜像短 ID镜像长 ID镜像名 或者 镜像摘要

我们可以用镜像的完整 ID,也称为 长 ID,来删除镜像。使用脚本的时候可能会用长 ID,但是人工输入就太累了,所以更多的时候是用 短 ID 来删除镜像。docker image ls 默认列出的就已经是短 ID 了,一般取前3个字符以上,只要足够区分于别的镜像就可以了。

操作容器

启动容器、

启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited)的容器重新启动。

因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。

未完待续

参考文章

更多详细教程请参考 前言 · Docker -- 从入门到实践 (docker-practice.github.io)

Docker “pull“命令获取镜像,讲道理你真的会吗?_docker pull_zhuzicc的博客-CSDN博客

Docker 教程 | 菜鸟教程 (runoob.com)

全面的Docker快速入门教程 - 知乎 (zhihu.com)

Docker 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)