# Docker

# 容器技术介绍

我们说的容器 container是指一项技术,而Docker只是一个容器技术的实现,或者说让容器技术普及开来的最成功的的实现。简单来说,容器技术是一种打包技术,它拥有以下三个特点:

  • 标准化
  • 轻量化
  • 易移植

# 容器技术的标准化

  • 容器会加速你的软件开发
  • 容器会加速程序的编译和构建
  • 容器会加速测试
  • 容器会加速故障修复

参考文档 (opens new window)

# 什么是Docker

Docker 是一个开源的应用容器引擎。开发者可以将自己的应用打包在自己的镜像里面,然后迁移到其他平台的 Docker 中。镜像中可以存放你自己自定义的运行环境,文件,代码,设置等等内容,再也不用担心环境造成的运行问题。镜像共享运行机器的系统内核。

同样, Docker 也支持跨平台。你的镜像也可以加载在 Windows 和 Linux,实现快速运行和部署。

# Docker解决了什么问题

一句话,解决了运行环境和配置问题的软件容器,方便于持续集成并有助于整体发布推动软件虚拟化技术。

# Docker三要素

  • 镜像 (image):

Docker镜像就是一个只读的模板,镜像可以用来创建docker容器,一个镜像可以创建很多容器。镜像其实是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的所有内容,包括代码、依赖、库、环境和配置文件, 可以理解为一个模板,镜像具有分层的概念

  • 容器(Container)

Docker利用容器(Container)独立运行的一个或者一组应用,容器是用镜像创建爱你的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证平台的安全。可以把容器看成是一个简单的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。容器的定义几乎和镜像一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

  • 仓库

是集中存放镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉取下来就可以了。

# Docker架构

docker架构

# Docker安装 (CentOS7)

在Docker安装之前,我们首先安装device-mapper-persistent-datalvm2 两个依赖。

device-mapper-persistent-dataLunix下的一个存储驱动,Linux 上的高级存储技术。

lvm2 的作用是创建逻辑磁盘分区,这里我们使用CentOS的Yum包管理工具安装两个依赖。

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

前置依赖

依赖安装完毕后,我们将阿里云的 Docker 镜像源添加进去。可以加速 Docker 的安装。

sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
1

最后安装 docker

yum install docker-ce -y
1

docker安装完毕

接着执行一下 docker -v ,这条命令可以用来查看 Docker 安装的版本信息。当然也可以帮助我们查看 docker 安装状态。如果正常展示版本信息,代表 Docker 已经安装成功。

如果我们在终端中输入:

docker version
1

会显示以下信息,下面的信息显示的docker在安装过程中安装了 客户端和服务端。

Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:42:56 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.10
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       e2f740d
  Built:            Mon Oct 25 07:41:17 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.11
  GitCommit:        5b46e404f6b9f661a205e28d59c982d3634148f8
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

docker安装完毕之后,需要重启docker,不然可能会遇到无法使用的情况。

Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running?
1
docker -v
1

验证版本

# 安装docker-compose

官方网站地址 (opens new window) 运行此命令以下载 Docker Compose 的当前稳定版本:

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
1

如果你想安装的版本不是1.29.2,直接替换这个版本号即可。

对二进制文件应用可执行权限

sudo chmod +x /usr/local/bin/docker-compose
1

# 安装完毕之后测试版本

docker-compose --version
1

# Docker安装 hello-world镜像

docker run hello-world
1

hello-world

从图中展示的信息可以看到,在执行run命令的时候,首先会从本地查找镜像,发现在本地没有找到,就去仓库中寻找,下载之后,基于这个镜像创建一个容器。

# Docker镜像常用命令

帮助命令

# 帮助命令
docker --help
1
2

在终端输入docker image 就能够列出 docker 关于镜像的所有操作方法:

$ docker image

Usage:  docker image COMMAND

Manage images

Commands:
  build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

Run 'docker image COMMAND --help' for more information on a command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

按照提示,进一步,如果想要查看某一个镜像的命令,可以继续操作, 例如:

$ docker image pull --help

Usage:  docker image pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)
      --platform string         Set platform if server is multi-platform capable
  -q, --quiet                   Suppress verbose output
1
2
3
4
5
6
7
8
9
10
11

列出本地主机上的所有镜像

# 列出本地主机上的所有镜像
docker images
1
2

镜像

各个选项说明:

  • REPOSITORY: 表示镜像仓库
  • TAG: 镜像标签
  • IMAGE ID: 镜像id
  • CREATED: 镜像创建时间
  • SIZE: 镜像大小

TIP

同一个仓库可以有多个TAG,代表这个仓库源的不同个版本,我们使用REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,将默认是使用最新的版本。

当然 docker images 后面还可以添加 options 参数:

docker images -a // 显示全部镜像,镜像是分层的
docker images -q // 只显示镜像的 images id
docker search xxx // 从dockerhub 中查找指定名称的镜像
docker search -s 30 xxx // 查找指定镜像在一定star数量之上的
docker pull xxx // 拉取指定名称的镜像 注意默认拉取的是最新的版本的镜像
docker rmi  xxx // 删除指定镜像 如果不添加任何标签默认删除最新版本的镜像
docker rmi -f xxx // 强制删除指定镜像
docker inspect 镜像id // 查看指定镜像的详细信息
1
2
3
4
5
6
7
8

如果我想要搜索 mongo 数据库,可以执行命令:

docker search mongo
1

如果我想拉取 mongo和centos镜像,可以执行命令:

# 默认拉取最新版本的镜像
docker pull mongo

# 拉取centos最新版本的镜像
docker pull centos

# 拉取指定版本的镜像(后面使用冒号指定版本号)
docker pull mongo:3.4.1

# 查看 id 0dffc7177b06 详细信息
docker inspect  0dffc7177b06
1
2
3
4
5
6
7
8
9
10
11

如果我想要删除 hello-world 这个镜像,可以执行命令:

docker rmi hello-world
1

当然我们还可以通过id删除镜像,分为两个步骤:

# 列出所有的镜像
$ docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
busybox               latest    16ea53ea7c65   5 months ago    1.24MB
nginx                 latest    ad4c705f24d3   5 months ago    133MB
outlinewiki/outline   latest    c2b92b5cd802   5 months ago    471MB
hello-world           latest    d1165f221234   11 months ago   13.3kB
easymock/easymock     1.6.0     193a7b904d4f   2 years ago     699MB
redis                 4.0.6     1e70071f4af4   4 years ago     107MB
mongo                 3.4.1     0dffc7177b06   5 years ago     402MB

# 执行 rmi 命令
$ docker rmi c2b92b5cd802 
1
2
3
4
5
6
7
8
9
10
11
12
13

# Docker容器常用命令

一般执行容器命令的时候 使用 docker container xxx 这种形式, 当然我们可以使用简写,将中间的 container 省略掉。

# 新建并启动容器

options说明:
--name="容器新名字":为容器指定一个名称
-d: 后台运行容器,并返回容器ID
-i: 以交互模式运行容器,通常与 -t 同时使用
-t: 为容器分配一个伪输入终端,通常与 -i 同时使用
-P: 随机端口映射
-p: 指定端口映射,有以下四种格式
  ip:hostPort: containerPort
  ip::containerPort
  hostPort: containerPort
  containerPort
1
2
3
4
5
6
7
8
9
10
11

# 列出当前所有正在运行的容器

docker ps

# 显示出当前我的服务器中启动的所有的容器
$ docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED        STATUS        PORTS                      NAMES
0c1c8d14921b   mongo:3.4.1               "/entrypoint.sh mong…"   43 hours ago   Up 43 hours   0.0.0.0:27017->27017/tcp   yapi-mongodb-docker
c9693a7fa9dd   easymock/easymock:1.6.0   "/bin/bash -c 'npm r…"   4 weeks ago    Up 3 hours    0.0.0.0:7300->7300/tcp     easy-mock_web_1
f506572bb5c7   mongo:3.4.1               "/entrypoint.sh mong…"   4 weeks ago    Up 3 hours    27017/tcp                  easy-mock_mongodb_1
4a7a0c8348a7   redis:4.0.6               "docker-entrypoint.s…"   4 weeks ago    Up 3 hours    6379/tcp                   easy-mock_redis_1
1
2
3
4
5
6
7
8
9

当然这个命令也是可以添加options的

-a 列出当前所有正在运行的容器 + 历史上运行过的
-l 显示最近创建的容器
-n 显示最近n个创建的容器
-q 静默模式,只显示容器编号
--no-trunc 不截断输出
1
2
3
4
5

docker ps -a

$ docker ps -a
CONTAINER ID   IMAGE                     COMMAND                  CREATED             STATUS                         PORTS                      NAMES
ea1732dfe8de   centos                    "/bin/bash"              16 minutes ago      Exited (0) 16 minutes ago                                 mycentos
3fe4caec1b0a   nginx                     "/docker-entrypoint.…"   18 minutes ago      Exited (0) 17 minutes ago                                 my-nginx
ebb4102ec952   nginx                     "/docker-entrypoint.…"   About an hour ago   Exited (0) About an hour ago                              nginx-server
0c1c8d14921b   mongo:3.4.1               "/entrypoint.sh mong…"   43 hours ago        Up 43 hours                    0.0.0.0:27017->27017/tcp   yapi-mongodb-docker
c9693a7fa9dd   easymock/easymock:1.6.0   "/bin/bash -c 'npm r…"   4 weeks ago         Up 3 hours                     0.0.0.0:7300->7300/tcp     easy-mock_web_1
f506572bb5c7   mongo:3.4.1               "/entrypoint.sh mong…"   4 weeks ago         Up 3 hours                     27017/tcp                  easy-mock_mongodb_1
4a7a0c8348a7   redis:4.0.6               "docker-entrypoint.s…"   4 weeks ago         Up 3 hours                     6379/tcp                   easy-mock_redis_1
0ffe03ebfdeb   hello-world               "/hello"                 2 months ago        Exited (0) 2 months ago                                   sad_jackson
1
2
3
4
5
6
7
8
9
10

# 启动容器

# 首先启动容器 进入交互式命令
$ docker run  -it --name mycentos centos
[root@941b40fa94aa /]#

# 退出交互式命令
[root@941b40fa94aa /]# exit
exit

# 退出容器之后,想要查看上一个刚退出的容器,可以看到,上次启动的是 mycentos 
$ docker ps -l
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                          PORTS     NAMES
941b40fa94aa   centos    "/bin/bash"   2 minutes ago   Exited (0) About a minute ago             mycentos
1
2
3
4
5
6
7
8
9
10
11
12

有时候,我们并不想使用交互式启动命令的方式,只想启动之后让它在后台运行,这个时候我们可以添加 -d 这个选项

# 我想要后台运行 centos 可以执行下面的命令
$ docker run -d centos
9a52cdc137ef7e2efef6919a5e296b555baf5524f1a1d82170f1c9c28b1e7a31

1
2
3
4

此时执行 docker ps 这个命令是查找不出来这个后台运行的容器的。执行 docker ps -a 是能够显示出来这个容器的,但是状态是退出的状态:

$ docker ps -a
CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS                     PORTS                      NAMES
9a52cdc137ef   centos                    "/bin/bash"              10 minutes ago   Exited (0) 9 minutes ago                              dazzling_clarke
0c1c8d14921b   mongo:3.4.1               "/entrypoint.sh mong…"   2 days ago       Up 2 days                  0.0.0.0:27017->27017/tcp   yapi-mongodb-docker
c9693a7fa9dd   easymock/easymock:1.6.0   "/bin/bash -c 'npm r…"   4 weeks ago      Up About an hour           0.0.0.0:7300->7300/tcp     easy-mock_web_1
f506572bb5c7   mongo:3.4.1               "/entrypoint.sh mong…"   4 weeks ago      Up 13 hours                27017/tcp                  easy-mock_mongodb_1
4a7a0c8348a7   redis:4.0.6               "docker-entrypoint.s…"   4 weeks ago      Up 13 hours                6379/tcp                   easy-mock_redis_1
0ffe03ebfdeb   hello-world               "/hello"                 2 months ago     Exited (0) 2 months ago                               sad_jackson
1
2
3
4
5
6
7
8

docker 容器的后台运行, 就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令,就是会自动退出的。这个是docker的运行机制问题。

# 重启容器

# docker restart 容器id 或者容器名称
# 比如我想重新启动easymock这个容器,可以执行命令
docker restart  c9693a7fa9dd
# 命令行返回 c9693a7fa9dd 说明重启成功
1
2
3
4

# 停止容器

docker stop 容器ID

docker stop  c9693a7fa9dd
1

# 强制停止容器

docker kill 容器ID

# 强制停止容器 c9693a7fa9dd
docker kill c9693a7fa9dd
1
2

# 删除已经停止的容器

docker rm 容器ID

# 删除已经停止掉的容器 c9693a7fa9dd
docker rm c9693a7fa9dd
1
2

# 查看容器内部细节

# 容器其实是一层一层的,这个命令可以显示内部的细节
docker inspect c9693a7fa9dd
1
2

# 拷贝docker中的文件到宿主机

docker cp 容器ID:容器内的路径 目标主机路径

# 将docker中nginx的配置文件拷贝到宿主机的cp目录下
docker cp xxxxx: /ect/nginx/nginx.conf /ect/nginx/cp/
1
2

# 以指定端口映射启动容器

# -p 宿主机端口:docker容器启动的端口 -d 指的是后台启动  --name 设置别名
docker run --name MyNginx -d -p 80:80  nginx

# 启动redis 指定版本的redis 使用的是冒号
docker run --name myredis -d -p 6379:6379 redis:4.0.6
1
2
3
4
5

# Docker容器数据卷

docker理念就是将应用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的,容器之间希望可以共享数据

docker容器产生的数据,如果不通过 docker commit 生产新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除之后,数据自然也就没有了。

为了能保存数据,在docker中我们卷的概念。

# 以nginx为例,在docker上启动nginx并配置容器数据卷

1、首先使用docker 拉取镜像,如果不加版本号,默认是最新版本

$docker pull nginx
1

2、使用docker 启动nginx

# -d 后台运行  -p 80:80 宿主机的端口映射nginx的端口 --name 别名
$docker run --name mynginx -d -p 80:80 nginx
1
2

3、重新开一个命令交互启动我们自己的nginx

$docker exec -it mynginx bash
1

4、我们想要修改nginx的配置文件

vim /etc/nginx/nginx.conf
1

执行上述命令发现容器内部实际上并没有安装 vim 这个工具,可以使用 apt-get 进行安装

# 更新源
$apt-get update

# 安装vim
$apt-get install vim
1
2
3
4
5

5、当然这种方式还是有些繁琐,我们可以把宿主机上的配置文件映射到 容器nginx容器里面

$docker run --name mynginx -d -p 80:80 -v /usr/local/docker/my-docker-nginx/vuepress:/usr/share/nginx/html/vuepress  -v /usr/local/docker/my-docker-nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf nginx 
1

解释下上述命令的含义:

  • docker run --name mynginx : 以 mynginx为别名启动nginx
  • -d: 代表的是后台启动
  • -p 80:80 用宿主机的80端口映射 docker容器中nginx的80端口
  • -v /usr/local/docker/my-docker-nginx/vuepress:/usr/share/nginx/html/vuepress 宿主机的vuepress目录映射到 docker容器中的文件目录
  • -v /usr/local/docker/my-docker-nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf 宿主机的文件替换容器文件
  • nginx 启动的是nginx

# 阿里云使用mongoDB

我已经在将docker3.4.1版本的镜像下载到阿里云上,一个镜像可以构建多个容器。

之前因为使用默认的端口号,并且没有设置密码,导致被黑客攻击。启动的时候需要替换一个不太常用的端口号。

$docker run --name myMongo -d -p 27898:27017 mongo:3.4.1
1

这样启动之后,阿里云的安全组需要重新配置,才能生效。

# 阿里云使用redis

我的阿里云服务器上已经下载好了redis镜像,下载的版本是redis:4.0.6

我的诉求是以指定的端口启动,防止被黑客攻击,映射到容器内的6379端口,并能够通过外网访问。

$docker run --name my-docker-redis -d -p 6978:6379 redis:4.0.6
1

这样启动之后,阿里云的安全组需要重新配置,才能生效。

# DockerFile

# Dockerfiles

# Docker Compose

docker-compose

最后更新时间: 11/19/2022, 10:40:46 AM