Docker 简介

Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从Apache2.0协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。

实验1 Docker镜像基本操作

本次实验包含docker基本操作,本次实验仅提供简单docker操作命令演示,更多操作请访问官方文档

1.1 实验之前可能需要手动启动 docker 服务

若docker可正常使用,则无需进行该1.1步骤所对应的操作

1
2
3
4
5
# kill掉docker僵死进程
# netstat -ntulp|grep 2376|awk '{printf $7}'|cut -d/ -f1 | xargs kill -9

# 手动启动docker服务
# /usr/local/bin/dockerd-entrypoint.sh &

待出现API listen on :::2376提示后,按下回车键,即可正常使用docker服务

此外,使用clear命令可以实现清屏功能~

1.2 查看本机所有的镜像

1
# docker images

实验环境中没有镜像,所以只输出头信息

输出:

image-20230401162257585

1.3 查找镜像

通过 docker search 命令查找镜像,如查找 alpine 镜像

1
# docker search alpine

部分输出结果如下:

1
2
3
4
5
6
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
alpine A minimal Docker image based on Alpine Linux… 5237 [OK]
mhart/alpine-node Minimal Node.js built on Alpine Linux 428
anapsix/alpine-java Oracle Java 8 (and 7) with GLIBC 2.28 over A… 406 [OK]
frolvlad/alpine-glibc Alpine Docker image with glibc (~12MB) 201 [OK]

输出结果:

image-20230401162406483

1.4 拉取镜像

查找到需要的镜像以后,可以通过 docker pull 命令拉取指定的镜像,以拉取 alpine 镜像为例

1
2
3
4
# docker pull alpine
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest cdf98d1859c1 3 weeks ago 5.53MB

如果不指定镜像标签,则默认拉取latest版本的镜像

输出:image-20230401162423580

1.5 构建镜像

当搜索不到需要的镜像时,可以使用 docker build 命令构建镜像,我们以 alpine:latest 为基础镜像,添加自定义脚本,并在容器启动时执行脚本,输出 “hello docker”

首先使用vi命令构建需要的文件,文件内容输入结束后使用:wq!保存文件

1
2
3
4
5
6
7
8
# vi /home/test.sh
echo "hello docker"

# vi /home/Dockerfile
FROM alpine:latest
ADD ./test.sh /test.sh
RUN chmod +x /test.sh
CMD ["/bin/sh", "-c", "/test.sh"]

查看test.sh文件,该脚本仅输出”hello docker”到终端,不执行其它操作

1
2
3
# cd /home
# cat test.sh
echo "hello docker"

查看 Dockerfile

1
2
3
4
5
# cat Dockerfile
FROM alpine:latest
ADD ./test.sh /test.sh
RUN chmod +x /test.sh
CMD ["/bin/sh", "-c", "/test.sh"]

输出结果:

image-20230401162447593

image-20230401162455130

构建镜像

1
# docker build -t hello-docker .

输出结果:

image-20230401162509100

运行构建的容器

1
2
# docker run --name hello-docker hello-docker
hello-docker

输出结果:

image-20230401162525662

可以看到容器正确执行了自定义到脚本

1.6 删除镜像

使用 docker rmi 命令可以删除一个镜像

实验2 容器基本操作

本次实验包含docker基本操作,本次实验仅提供简单docker操作命令演示,更多操作请访问官方文档

2.1 查看本机所有容器

使用 docker ps 命令可以查看本机正在运行的容器

1
# docker ps

当前没有正在运行的容器,所以只输出头信息

输出:

image-20230401162542940

使用 docker ps -a 命令可以查看所有的(包括停止的)容器

1
2
3
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67c35fbd2030 hello-docker "/bin/sh -c /test.sh" About a minute ago Exited (0) About a minute ago hello-docker

可以看到上一节实验中运行过的 hello-docker 容器

输出结果:

image-20230401162600076

2.2 创建容器

使用 docker create 命令可以创建新的容器,例如基于hello-docker镜像创建一个名为my-container的容器

1
2
# docker create --name my-container hello-docker:latest
177f676188754f2fe48ffa2ac18a499f25c00708fa43d8f4253092802025d0a3

创建完成后,会输出新创建的容器的ID,注意,此时只是创建了容器,并没有运行容器。

输出结果:

image-20230401162613428

2.3 启动容器

创建完容器以后,可以通过 docker start 命令启动容器,例如启动上面创建的 my-container 容器

1
# docker start -i my-container

ID需要填入读者自己创建容器时输出的ID,启动容器以后默认不输出信息到控制台,因此,需要加 -i 参数将输出信息重定向到控制台。

输出结果:

image-20230401162626825

2.4 查看容器信息

使用 docker inspect <ID|Name> 命令查看容器信息,例如查看上面创建的 my-container 容器

1
# docker inspect my-container

输出结果:

image-20230401162638405

2.5 直接运行容器

可以通过先创建后运行的方式运行一个容器,也可以通过 docker run 命令直接运行一个容器,如运行一个 hello-docker 容器

1
2
# docker run hello-docker
hello-docker

输出结果:

image-20230401162652259

2.6 后台运行容器

hello-docker 容器只输出一句 “hello docker” 便退出了,而像 mysql、nginx 这些容器需要一直保持后台运行状态,此时,我们可以使用 -d 参数让容器在后台运行,例如:

1
# docker run -d --hostname nginx --name nginx nginx:alpine

输出结果:

image-20230401162707010

测试容器运行情况:

首先查看容器的IP地址

1
# docker inspect nginx

部分输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "b62a412ff73bfcae29ee9c7fe7460b07c41ebab138907270b0066a2785e5cedf",
"EndpointID": "02347c1c388825d2b28c18eb892c745229c07c58f3d4a46135c879977a359cf1",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:02",
"DriverOpts": null
}
}

IP地址为 172.18.0.2(以实际输出为准)

实际输出:

image-20230401162730217

请求 nginx 首页

1
# curl 172.18.0.2 (IP地址以实际输出信息为准)

输出内容如下:(因基础镜像的原因,curl工具在当前实训环境中不可用,同学们可参考以下输出)

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
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

可以看到容器在后台运行,并且正确请求到了nginx首页信息

2.7 进入容器 shell 环境

使用 docker exec 命令可以与容器进行交互,例如与 nginx 容器进行交互

1
# docker exec -it nginx sh

此时进入容器的 shell 环境,使用exit命令可以退出容器 shell

1
# exit

2.8 查看容器运行日志

使用 docker logs <ID|Name> 查看容器运行日志,例如查看nginx容器运行日志:

1
2
# docker logs nginx
172.18.0.1 - - [03/May/2019:07:21:31 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

输出结果:

image-20230401162753836

2.9 停止容器

使用 docker stop <ID|Name> 停止容器

1
2
# docker stop nginx
nginx

nginx容器已经停止

输出结果:

image-20230401162807364

2.10 删除容器

使用 docker rm <ID|Name>命令可以删除容器

1
# docker rm nginx

如果nginx容器正在运行,则会提示删除错误,需要先停止nginx容器再删除,或者添加 -f 参数强制删除

输出结果:

image-20230401162818841

1
2
# docker rm -f nginx
nginx

实验3 volume基本操作

在本节课程中,你将学习如何在容器内使用 docker volumes 来持久数据。docker volumes 允许在容器和容器版本之间共享目录。

docker volumes 允许你升级容器、重启机器和共享数据,而不会造成数据丢失。在更新数据库或应用程序版本时,这是必不可少的。

当容器启动时,docker volumes 被创建和分配。数据卷允许你讲主机目录映射到容器里,以便共享数据。

这种映射是双向的。它允许存储在主机上的数据从容器中访问。它还意味着容器内进程保存的数据保存在主机上。

本次实验仅提供简单docker操作命令演示,更多操作请访问官方文档

3.1 查看本机数据卷

使用 docker volume ls 命令查看本机的volume

1
2
# docker volume ls
DRIVER VOLUME NAME

初始状态没有volume,所以仅输出头信息

输出结果:

image-20230401162834041

3.1 创建volume

使用 docker volume create 创建数据卷,例如创建一个名为 nginx-v 的 volume

1
2
# docker volume create nginx-v
nginx-v

输出结果:

image-20230401162844127

3.2 查看 volume 信息

使用 docker inspect 查看 volume 信息

1
2
3
4
5
6
7
8
9
10
11
12
# docker inspect nginx-v
[
{
"CreatedAt": "2019-05-03T07:33:20Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/nginx-v/_data",
"Name": "nginx-v",
"Options": {},
"Scope": "local"
}
]

可以看到,nginx-v 数据卷的主机路径为 /var/lib/docker/volumes/nginx-v/_data

输出结果:

image-20230401162900356

3.3 挂载 volume

在运行容器时,需要指定数据卷进行挂载,我们运行 nginx 容器,并挂载已创建的 nginx-v 数据卷

1
# docker run -d --name nginx-2 -v nginx-v:/var/log/nginx nginx:alpine

image-20230401162933200

这条命令将 nginx-v 挂载到容器的 /var/log/nginx 目录,访问本机的 /var/lib/docker/volumes/nginx-v/_data 目录,即相当于访问容器的 /var/log/nginx 目录

首先查看本机的/var/lib/docker/volumes/nginx-v/_data目录

1
2
# ls /var/lib/docker/volumes/nginx-v/_data
access.log error.log

image-20230401162947235

其中,access.log error.log 2个文件为容器中nginx创建的文件

在本机的 /var/lib/docker/volumes/nginx-v/_data 创建一个测试文件

1
# echo "hello volume" > /var/lib/docker/volumes/nginx-v/_data/test

查看容器中的 /var/log/nginx/test 文件

image-20230401163000019

1
2
# docker exec -it nginx-2 cat /var/log/nginx/test
hello volume

可以看到输出内容即为在主机上写入的 “hello volume”

3.4 直接挂载数据卷

前面通过先创建再挂载的方式使用数据卷,docker命令行支持在创建容器时直接创建数据卷

下面这条命令将主机的 /docker 目录挂载到容器的 /volume/docker 目录

1
2
# docker run -it -v /docker:/volume/docker alpine ls /volume/docker
Dockerfile test.sh

image-20230401163151563

3.4 共享volume

映射到主机的数据卷对于持久化数据非常有用。但是,为了从另一个容器中获得它们,你需要做的确切的路径,这会使它容易出错。另一种方法是使用 -volumes-from。参数将映射的卷从源容器映射到正在启动的容器。 在这种情况下,我们将 nginx-2 容器的卷映射到一个 alpine 容器。

1
2
# docker run --volumes-from nginx-2 -it alpine ls /var/log/nginx
access.log error.log test

image-20230401163203838

可以看到,在新创建的alpine容器中,可以正常访问 nginx-v 数据卷的内容,实现了容器间共享数据卷

3.5 删除volume

检查是否有容器正在占用待删除Volume:

删除数据卷volume的话,需要删除对此volume进行占用的所有容器,比如使用docker volume rm 删除数据卷的时候,可能报错,”Error response from daemon: remove nginx-v: volume is in use - 357302956d67…“,使用docker ps -a命令查看所有容器,我们可以看到CONTAINER ID为357302956d67的容器(NAMES为nginx-2),正是此容器在占用待删除volume,我们需要将此容器进行删除。

删除占用volume的容器,可以通过docker rm -f 或者docker rm -f删除容器

1
# docker rm nginx-2 -f

然后我们就可以通过 docker volume rm 可以删除一个数据卷

1
# docker volume rm nginx-v

(此时如果容器正在运行,则会提示删除数据卷失败,需要先删除容器,再删除数据卷)

image-20230401163218183

image-20230401163222403