Docker入门

一、Docker概述

1.Docker的作用
一款产品的开发往往需要多个开发环境,在以前,开发人员将项目打包好之后,经常会出现在我的电脑上能够正常运行,而在他的电脑上不能使用,原因就是产品开发所需要的环境不一样。

而现在,开发人员将产品以及它所对应的开发环境一起打包,这种就被称为镜像。这样就省去了开发环境的麻烦。

而docker的出现就是为了解决以上的问题,docker就相当于一个箱子(镜像),把每一个镜像隔离开来,互不干扰。

1.镜像

镜像就相当于一个印刷机的模板,可以通过镜像来创建多个容器,也就是可以靠印刷机的模板印刷出很多相同的书籍,各个容器之间相互独立。

2.容器

容器就是一个一个独立的应用,每个应用之间相互独立
可以被启用、开始、停止、删除。足够安全
可以把容器看作是一个简易版的Linux系统(包括root用户权限,进程空间,用户空间和网络空间等)和运行在其中的应用程序。

3.仓库

仓库是集中存放镜像文件的地方。
仓库和仓库注册服务器(Registry)是有区别的,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签
仓库分为公开仓库(public)和私有仓库(private)两种形式
最大的仓库是国外的Docker Hub,存放了大量的镜像文件。

二、Docker工作原理

1.Docker的工作原理

Dokcer是一个Client-Server结构:Docker守护进程运行在主机上,通过Socket从客户端来访问这个守护进程,而守护进程接收到来自客户端的命令后,管理运行在主机上的容器以及进行资源的分配。

三、命令

容器命令

有了镜像才可以创建容器

说明:我们有了镜像才可以创建容器,Linux 下载一个centos镜像来测试学习

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker run[可选参数] image
#参数说明
--name= "NAME" 容器名字 tomcat1 tomcat2,用来进行区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-P 指定容器的端口 -p 8080:8080
-p主机端口:容器端口(常用)
-p容器端口
容器端口
-p 随机指定端口


# 启动并进入容器
PS C:\Users\17083\Desktop> docker run -it centos
[root@6c35f43ce5c2 /]# exit
exit
PS C:\Users\17083\Desktop> docker run -it centos /bin/bash
[root@9e59d793d8dc /]#

docker中创建容器的两种方式(交互式与守护式)

当使用Docker时,有两种常见的方式来创建容器:交互式方式和守护(后台)式方式。

交互式方式创建容器

交互式方式创建容器是指在容器内部启动一个交互式会话,类似于在终端中登录到一个虚拟机。您可以直接与容器进行交互,并在容器内部执行命令。

守护(后台)式方式创建容器

守护式方式创建容器是指在后台运行容器,无需进入容器内部进行交互。这种方式适用于长期运行的服务或应用程序。

列出所有运行的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 列出当前正在运行的容器 + 带出历史运行过的容器
PS C:\Users\17083\Desktop> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e59d793d8dc centos "/bin/bash" 4 minutes ago Exited (127) 8 seconds ago
agitated_shtern
6c35f43ce5c2 centos "/bin/bash" 4 minutes ago Exited (0) 4 minutes ago
elastic_brahmagupta
63684c89095b jenkins/jenkins:jdk11 "/usr/bin/tini -- /u…" 10 days ago Exited (255) 6 days ago 50000/tcp, 0.0.0.0:9090->8080/tcp jks
# 列出当前正在运行的容器
PS C:\Users\17083\Desktop> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 列出最近创建的容器
PS C:\Users\17083\Desktop> docker ps -a -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e59d793d8dc centos "/bin/bash" 7 minutes ago Exited (127) 3 minutes ago agitated_shtern
# -q只显示容器的编号
PS C:\Users\17083\Desktop> docker ps -aq
9e59d793d8dc
6c35f43ce5c2
63684c89095b

退出容器

1
2
3
exit #容器停止并退出
Ctrl + P + Q #容器不停止退出
docker exec -it [容器NAMES] /bin/bash #容器不停止退出,重新进入这个容器

删除容器

1
2
3
docker rm [容器id]                  #删除指定的容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器

启动和停止容器的操作

1
2
3
4
docker start[容器id]              #启动容器
docker restart[容器id] #重启容器
docker stop[容器id] #停止容器
docker kill[容器id] #杀死容器

常用的其他命令

后台启动容器

1
2
3
4
# docker run -d 镜像名
docker run -d centos
# 问题:docker ps -a 发现centos停止了
## 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志的命令

1
2
3
4
5
6
7
8
9
10
11
docker logs -t -f --tail #如果容器中没有日志
#自己写一个脚本
docker run -d centos /bin/bash -c "while true;do echo yll;sleep 1;done"

PS C:\Users\17083\Desktop> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7df27afdfd97 centos "/bin/bash -c 'while…" 30 seconds ago Up 29 seconds elegant_pascal
#显示日志
-tf
--tail [number] #要显示的日志数量 + 容器id
docker logs -t -f --tail 10 7df27afdfd97

查看容器中的进程信息ps

1
2
3
4
5
# top命令
PS C:\Users\17083\Desktop> docker top 7df27afdfd97

UID PID PPID C STIME TTY
root 25077 24273 0 06:35 ?

查看镜像元数据

1
2
3
#命令
docker inspect [容器id]
PS C:\Users\17083\Desktop> docker inspect 7df27afdfd97

进入当前正在运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#我们通常容器都是使用 后台的方式进行运行的,需要进入容器修改一些配置
#命令1
# -it以交互模式执行
docker exec -it [容器id] [bashshell]

#测试
PS C:\Users\17083\Desktop> docker exec -it 7df27afdfd97 /bin/bash
[root@7df27afdfd97 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
#命令2
dcoker attach [容器id]
正在执行当前的代码......
#docker exec #进入容器后开启一个新的终端
#docker attach #进入容器正在执行的终端,不会启动新的进程!

从容器中拷贝文件到主机上

1
2
3
4
docker cp 容器id: 容器内的路径 目的主机的路径
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker cp d574485cf29a:/home/test.java /mnt/c/Users/17083/Desktop
Successfully copied 1.54kB to /mnt/c/Users/17083/Desktop
# 拷贝是一个手动的过程,未来我们使用-v卷的技术,可以实现自动同步 /home /home

练习

Docker安装nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1、搜索镜像
docker search nginx
#2、下载镜像
dcoker pull nginx
#3、运行测试
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口,容器内部的端口
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker run -d --name nginx01 -p 3344:80 nginx
a92da888d3aa44846b8dcbd278e530b443c4e46af7852078a780e0bde101b6ac
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92da888d3aa nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp nginx01
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# curl localhost:3344
#进入容器
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a92da888d3aa nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:3344->80/tcp nginx01
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker exec -it nginx01 /bin/bash
root@a92da888d3aa:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@a92da888d3aa:/# cd /etc/nginx
root@a92da888d3aa:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params

每次改动nginx配置文件,都需要进入容器的里面,十分麻烦,我要是可以在容器外提供映射路径,达到在容器外面修改文件,容器内部就可以自动修改。-v:数据卷

docker安装一个tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#官方的使用方法
docker run -it --rm tomcat:9.0
#我们之前的启动都是后台,停止了容器之后,容器还可以再查得到 docker -it --rm tomcat:9.0,一般用来进行测试,用完就删除

#先下载,再启动
docker pull tomcat
#启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat

#测试访问没有问题
cp -r webapps.dist/* webapps
#进入容器 # 将webapps.dist中的全部内容复制到webapps中去
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop # docker exec -it tomcat01 /bin/bash

#发现它没有webapps,镜像的原因,默认是最小的镜像,所有不必要的都会剔除,保证最小的可运行的环境!

如果每次进入容器都会非常的麻烦,我们要是可以在容器的外面提供一个映射的路径,webapps,我们再外面放置项目,就自动同步到内部就很好了。

部署es + kibana

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
29
# elasticsearch 暴露的端口很多
# elasticsearch 十分的消耗内存
# elasticsearch 的数据一般要放置到安全的目录下!挂载
# --net somenetwork ?网络配置
# 启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#它是非常消耗内存的
localhost:9200
{
"name": "4cd6c3d1f871",
"cluster_name": "docker-cluster",
"cluster_uuid": "XU3rNb8-T6Cu-NSzBd7ykA",
"version": {
"number": "7.6.2",
"build_flavor": "default",
"build_type": "docker",
"build_hash": "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date": "2020-03-26T06:34:37.794943Z",
"build_snapshot": false,
"lucene_version": "8.4.0",
"minimum_wire_compatibility_version": "6.8.0",
"minimum_index_compatibility_version": "6.0.0-beta1"
},
"tagline": "You Know, for Search"
}

# 增加内存限制,修改配置文件 -e环境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms64m -Xmx512m" elasticsearch:7.6.2

使用kibana连接elasticsearch

四、可视化面板

  • portainer(先用这个)

  • Rancher(CI/CD)

什么是portainer

Docker图形化界面管理工具!提供一个后台面板供我们操作

1
2
Docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问测试:Portainer,可以看到

五、Docker 镜像讲解

1、镜像是什么?

镜像是一种轻量级的、可执行的独立的软件包,用来打包软件运行环境开发的软件,它包含某个软件所需要的所有内容,包括代码、运行时、库、环境变量和配置文件。

将所有的应用和环境,直接打包为Docker镜像,就可以直接运行。

如何得到镜像 ?

  • 从远程仓库下载
  • 拷贝
  • 自己制作一个DockerFile

2、Docker镜像加载原理

UnionFs(联合文件系统)

UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。

黑屏–(加载)–开机进入系统

rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.

虚拟机是分钟级别,容器是秒级!

3、分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层层的在下载 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@LAPTOP-10L6P3UV:/mnt/c/Users/17083/Desktop# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
09f376ebb190: Already exists # 明显这一层已经下载了
9ae6a7172b01: Pull complete
2c310454138b: Pull complete
3eba9ec960aa: Pull complete
3d36c165ff0a: Pull complete
493d196d734f: Pull complete
4f4fb700ef54: Pull complete
484e0560ae90: Pull complete
Digest: sha256:01afb31d6d633451d84475ff3eb95f8c48bf0ee59ec9c948b161adb4da882053
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
思考:

为什么Docker镜像要采用这种分层的结构呢?

最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过docker image inspect 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"RootFS": {
"Type": "layers",
"Layers": [
# 第一步已经下载过了,剩下的再一步一步安装,每次安装一部就是一个记录
"sha256:5d4427064ecc46e3c2add169e9b5eafc7ed2be7861081ec925938ab628ac0e25",
"sha256:12c0b39a3b9d0dab1c5cbcb18cb220ee002110f1afedad16e2d7ff206aef3c9e",
"sha256:304555e2fff0c025082f15d5c33cb2497e128032db726375739930040e044863",
"sha256:8af05c1dad089b41305326247dbd3b10e83f667c74f80cc289ca081f5c7448c3",
"sha256:56c72ac4e9c6d764f3f7cecbde503aefe6a5fb6e6d354074013a9dd55722c1d1",
"sha256:1f3cf62067a933ee78a2cd500fb3fc7434cf99cdcebf062d099f0d57df01972b",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:d1b598028f26907d399516f3957eed2c6dd8f21c6c3772385de74b0b54031b6d"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"

所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当 前已经包含3个镜像层。例如:在外部看来整个镜像只有6个文件,这是因为最上层中的文件7 是文件5的一个更新版,这种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新 镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的。件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW [1]。

特点

Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

如何提交一个自己的镜像

4、Commit镜像

1
2
docker commit 提交容器成为一个新的副本
docker commit -m "提交的描述信息" -a="作者" 容器id 目标镜像名,[tag]

实战测试

1
2
3
4
5
6
7
8
9
# 1、启动一个默认的tomcat
docker run -d -p 8080:8080 tomcat
# 2、发现这个默认的tomcat 是没有webapps应用,官方的镜像默认webapps下面是没有文件的!
docker exec -it 容器id
# 3、我自己拷贝文件进去
cp -r webapps.dis/* webapps
# 4、将操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -a="kuangshen" -m="add webapps app" 容器id tomcat02:1.0

如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比我们我使用虚拟机的时候,快照!,到了这里Docker才算入门


Docker入门
http://example.com/2024/06/02/docker1_basic/
作者
nianjx
发布于
2024年6月2日
许可协议