docker

持续更新中..

一、 简介

1 虚拟化技术

虚拟化技术是一种资源管理技术,是将计算机的各种实体资源(CPU、内存、磁盘空间、网络适配器等),予以抽象、转换后呈现出来并可供分割、组合为一个或多个电脑配置环境。虚拟机和docker都属于虚拟化技术的一种。

2 容器技术

容器技术属于虚拟化技术。当一个项目仅由几个大组件构成的时候,可以为它们单独创建虚拟机,为它们提供完全独立的环境(分配独立的硬件环境);但是,但这些组件逐渐解耦成为更小的组件,它们的数量逐渐增长,为它们一一分配虚拟机是浪费资源的行为,并且大大增加了系统管理员和运维人员的负担。

容器技术应运而生地解决了这个问题,它的开销相比虚拟机小很多,并且在一台机器上允许运行多个相互隔离的服务。在宿主机看来,一个容器不过是一个运行的进程,在容器本身看来,就好像是机器和操作系统上运行的唯一一个进程。

3 虚拟机和容器比较

虚拟机和容器比较,容器更加轻量。因为容器直接运行在宿主机的操作系统上,虚拟机则需要创建出虚拟的硬件资源,将操作系统跑在这些硬件资源之上。

但是虚拟机的好处是它们提供完全隔离的环境,每个虚拟机运行在自己的linux内核上,而容器直接调用宿主机的内核。

4 doker简介

Docker 是一个开源软件,是一个开放平台,用于开发应用、交付(shipping)应用、运行应用。 Docker允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。

Docker容器与虚拟机类似,但二者在原理上不同。容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。 与传统的虚拟机相比,Docker优势体现为启动速度快、占用体积小。

另外,docker容器镜像是多层构成,它可以在多个镜像之间共享和使用。举例来说,如果你下载了一个centos7镜像,再去下载一个mysql镜像,mysql镜像所需的一些层在centos7镜像中已经存在,那么后面下载的mysql镜像就无须下载重复的层。

二、安装与启动

1 CentOS

要安装Docker引擎,需要CentOS 7或CentOS 8的维护版本,更早的版本并不推荐安装。这里以CentOS7为例:

如果已经安装,卸载docker

1
2
3
4
5
6
7
8
9
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
rm -rf /var/lib/docker

将yum更新

1
yum update

安装必要的软件包,它提供yum-config-manager, device mapper存储驱动程序需要 device-mapper-persistent-data 和 lvm2

1
yum install -y yum-utils device-mapper-persistent-data lvm2

配置源(官方源),如果下载慢,可以切换到阿里源

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

配置源(阿里源)

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

安装docker

1
yum -y install docker-ce

开启docker服务

1
systemctl start docker

查看docker版本

1
docker -v

三、镜像与容器的基本操作

镜像是一个Docker的可执行文件,其中包括运行应用程序所需的所有代码内容、依赖库、环境变量和配置文件等。用户基于镜像来运行自己的容器,镜像体积小,便于更新。容器基于镜像构建,一个镜像可以构建多个容器,容器启动完成后,我们可以登录到容器中安装自己需要的软件或者服务。

1 镜像基本操作

1.1 查找镜像

要获取镜像,需要从网络中查找镜像。docker镜像仓库存放了众多镜像,你可以去官方提供的仓库,也可以自己搭建一个。你可以把你的镜像上传到仓库,也可以下载别人的镜像,但是有些仓库是私有的,仅部分人可以接入,有些则是公开的,所有人都可以拉取。

1
docker search 镜像名

image-20211201145426503

1
2
3
4
5
NAME:仓库名
DESCRIPTION:镜像描述
STARS:和github star一样
OFFICIAL:来自于官方
AUTOMATED:自动构建,该镜像是由Docker Hub自动构建流程创建的

除了在命令行操作外,还可以去官网查询。类似于github,这是docker镜像的远程仓库。

image-20211201144937026

1.2 拉取镜像

1
docker pull 镜像名

比如要拉取mysql

1
docker pull mysql:5.7 # 冒号后指定版本,不指定版本则获取最新

image-20211201143338929

1.3 查看镜像

可以查看当前所有镜像。

1
docker images

image-20211202172321868

字段说明

1
2
3
4
5
REPOSITORY:镜像名称
TAG:镜像标签
IMAGE ID:镜像ID
CREATED:镜像的创建日期
SIZE:镜像大小

1.4 删除镜像

1
docker rmi 镜像ID(或者镜像名)

删除所有镜像

1
docker rmi `docker images -q`

2 容器基本操作

docker容器通常是一个linux容器,一个运行中的容器时宿主机上的一个进程,但是这个进程和其它进程之间相互隔离,并且也是资源受限的。你可以基于镜像创建出多个容器。

2.1 查看容器

查看正在运行的容器

1
docker ps

查看所有容器(包括没有运行的容器)

1
docker ps -a

查看上一次运行的容器

1
docker ps –l

2.2 创建并启动容器

1
docker run -di --name=容器名 镜像名称:标签(tag)

举例:

1
2
docker run -di --name=sql mysql:5.7
docker run -ti --name=sql mysql:5.7

image-20211202172538144

如图,以守护式创建容器,会返回一个容器ID。

参数说明:

1
2
3
4
5
6
7
-i: 以交互模式运行容器(启动容器),通常与 -t 同时使用
-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个虚拟终端
--name:容器名
-d: 创建一个守护式容器在后台运行,并返回容器ID
-e:设置容器中运行时的环境变量
-p: 指定端口映射
-v: 指定目录映射关系,将容器与宿主机目录映射

2.3 停止、启动容器

停止容器

1
docker stop 容器名称(或者容器ID)

启动容器

1
docker start 容器名称(或者容器ID)

停止所有容器(用命令查询出所有正在运行的的容器id,一起停掉)

1
docker stop `docker ps -q`

2.4 删除容器

删除前,确保该容器已经停止。

1
docker rm 容器名称(容器ID)

删除所有容器

1
docker rm `docker ps -a -q`

2.5 容器重命名

1
docker rename 容器名 新容器名

2.6 查看容器详细信息

1
docker inspect 容器id(或者容器名)

image-20211202191740664

可以查看到所有的详细信息,json格式。常用的字段是容器的ip地址,可以通过以下命令直接获取

1
docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称(或者容器ID)

image-20211202192053965

3 操作容器

3.1 在容器内执行命令

如果以-ti启动容器,那么前台会直接创建一个虚拟终端(bash窗口)供操作容器。

如果以-di创建容器,并不会启动,而是创建一个守护式容器,使用以下命令创建一个bash操作:

1
docker exec -it 容器名称 (或者容器ID)  /bin/bash

image-20211202172722546

退出容器(退出bash):

1
exit

注意,如果是-it创建虚拟终端操作容器,exit退出时,相应的docker进程同时结束。如果是-id创建守护式容器,再exec -it操作容器,exit退出时,前台进程退出,但后台docker守护进程不会结束。

docker exec命令实际是在容器内执行命令,因此如果执行/bin/bash创建一个bash窗口,即可在bash内操作容器(像在容器内操作一样)。

3.2 将文件拷贝到容器

使用拷贝命令,可以让宿主机和容器进行文件传输交互。

从宿主机拷贝到容器:

1
docker cp 需要拷贝的文件或目录 容器名称:容器目录

从容器拷贝到宿主机:

1
docker cp 容器名称:容器目录 需要拷贝的文件或目录

示例如图:

image-20211202173237333

由于是拷贝文件,删除掉原文件,另外一个也可以正常打开。

4 将容器保存为镜像

4.1 从容器创建一个新的镜像

可以在原有的容器上安装一些文件,然后把新的容器打包为镜像。

1
docker commit 容器名 镜像名

image-20211203101531167

4.2 将镜像保存为tar文件

将一个或多个镜像打包成tar文件导出。

1
2
docker save -o IMAGE [IMAGE...]
-o :输出到的文件

举例,将python-django镜像打包

1
docker save -o python-django.tar python-django

image-20211203102245385

4.3 将tar备份文件导入为镜像

将docker save的文件导入。

1
2
docker load -i 要导入的tar文件
-i : 指定导入的文件

举例,将tar文件导入到镜像。

1
docker load -i python-django.tar

四、其它

1 添加代理

1.1 dockerd代理

在拉取镜像过程中,由于一些原因,可能需要添加dockerd代理:

在执行docker pull时,是由守护进程dockerd来执行。因此,代理需要配在dockerd的环境中。而这个环境,则是受systemd所管控,因此实际是systemd的配置。

1
2
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo touch /etc/systemd/system/docker.service.d/proxy.conf

在这个proxy.conf文件(可以是任意*.conf的形式)中,添加以下内容:

1
2
3
4
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080/"
Environment="HTTPS_PROXY=http://proxy.example.com:8080/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com" # 不使用代理的地址

dockerd 代理的修改比较特殊,它实际上是改 systemd 的配置,因此需要重载 systemd 并重启 dockerd 才能生效:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

1.2 dockerbuild代理

虽然 docker build 的本质,也是启动一个容器,但是环境会略有不同,用户级配置无效。在构建时,需要注入 http_proxy 等参数。

1
2
3
4
5
docker build . \
--build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \
--build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \
--build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
-t your/image:tag

注意:无论是 docker run 还是 docker build,默认是网络隔绝的。如果代理使用的是 localhost:3128 这类,则会无效。这类仅限本地的代理,必须加上 --network host 才能正常使用。而一般则需要配置代理的外部IP,而且代理本身要开启 Gateway 模式。

docker build 代理是在执行前设置的,所以修改后,下次执行立即生效。

1.3 容器代理

在容器运行阶段,如果需要代理上网,则需要配置 ~/.docker/config.json。以下配置,只在Docker 17.07及以上版本生效。

1
2
3
4
5
6
7
8
9
10
11
{
"proxies":
{
"default":
{
"httpProxy": "http://proxy.example.com:8080",
"httpsProxy": "http://proxy.example.com:8080",
"noProxy": "localhost,127.0.0.1,.example.com"
}
}
}

这个是用户级的配置,除了 proxiesdocker login 等相关信息也会在其中。而且还可以配置信息展示的格式、插件参数等。

此外,容器的网络代理,也可以直接在其运行时通过 -e 注入 http_proxy 等环境变量。这两种方法分别适合不同场景。config.json 非常方便,默认在所有配置修改后启动的容器生效,适合个人开发环境。在CI/CD的自动构建环境、或者实际上线运行的环境中,这种方法就不太合适,用 -e 注入这种显式配置会更好,减轻对构建、部署环境的依赖。当然,在这些环境中,最好用良好的设计避免配置代理上网。