跟随狂神学Java-44,Docker
Joker2Yue第四十四:Docker
“弱小无知不是生存的障碍,傲慢才是”
初始Docker
什么是Docker
Docker是一种开源平台和工具,用于容器化应用程序。容器是一种轻量级、可移植的封装,其中包含应用程序和其依赖的所有组件,包括代码、运行时、库、环境变量和配置文件。Docker的主要目标是使应用程序在不同的环境中具有一致的运行方式,并提供更高效的资源利用和部署过程。
Docker的优势包括简化应用程序的开发、测试和部署过程,提高了资源利用率,使开发人员能够更容易地构建和交付应用程序。它在容器化技术方面的普及使得容器化应用程序在云计算和DevOps领域得到广泛应用。
Docker为什么会出现
Docker之所以出现,是为了解决软件开发和部署过程中的环境一致性问题。在传统的软件开发过程中,开发环境和生产环境通常是不同的,这可能导致以下问题:
-
环境差异导致问题:由于开发环境和生产环境的差异,开发人员在开发阶段无法完全模拟生产环境,导致在上线后可能出现意外的问题。这些问题可能包括依赖项不匹配、配置不一致以及操作系统或库的差异。
-
依赖管理困难:在传统的环境中,管理应用程序所需的依赖项(例如库、框架、运行时环境等)通常是复杂和耗时的(集群中环境的配置)。不同的应用程序可能需要不同版本的依赖项,这可能导致冲突和管理困难。
-
开发与运维隔离:传统的开发和运维过程通常是分离的,开发人员编写应用程序后,需要将其移交给运维团队进行部署。这可能导致部署过程不流畅,而且难以协作和快速交付。
Docker的出现解决了这些问题。Docker允许开发人员将应用程序和其所有依赖项封装到一个称为容器的单独单元中。容器包含了应用程序的代码、依赖项、运行时环境和配置,以及操作系统的一部分。这意味着开发人员可以在其开发环境中创建一个与生产环境几乎相同的容器,确保了环境的一致性。
Docker的思想来自于集装箱,将每套环境打包装箱,相互隔离。
Docker的历史
在2010年,一群年轻的IT专业人士在美国创立了名为dotcloud的公司,专注于提供Platform as a Service(PaaS)云计算服务。他们开始使用与LXC(Linux容器)相关的容器技术来解决他们自己的开发和部署问题。
这个公司决定将他们的容器技术命名为Docker,并试图将其推向市场。然而,在刚刚诞生的时候,Docker并没有引起行业的广泛关注,而dotcloud公司也陷入困境。
然后,在2013年,Docker决定开源他们的技术,这一举措改变了一切。人们开始注意到Docker的优点,特别是其轻巧性。在容器技术兴起之前,虚拟机技术是主流,但虚拟机相对笨重,需要在每个虚拟机中运行完整的操作系统。而Docker容器技术允许多个容器在同一个操作系统上共享内核,因此更加轻巧和高效。
比较虚拟机和Docker容器,虚拟机需要运行完整的操作系统,而Docker容器只包含应用程序和其依赖项,因此更小巧。这使得Docker在资源利用和部署速度方面具有明显的优势。
随着Docker的持续发展和改进,它于2014年发布了1.0版本,正式迈入了成熟阶段。Docker的火爆程度得益于其轻便和高效的特性,以及对开发和部署流程的极大改进,这使得它成为了现代软件开发和部署的主要工具之一。
关于Docker
-
基于Go语言开发的开源项目
-
官方文档:Docker Docs
-
仓库地址:Docker Hub Container Image Library | App Containerization
Docker能做什么
-
传统的虚拟机机制
-
缺点:
资源占用大
冗余步骤多
启动速度慢
-
-
Docker的容器化技术
-
容器化技术不是模拟一个完整的操作系统,它们之间相互隔离,互不影响
-
-
比较
特点 Docker 虚拟机技术 架构层次 容器化技术,共享操作系统内核 完整虚拟化,每个虚拟机有独立操作系统 资源利用 高效,轻量级,共享资源 相对较高,独立虚拟机需额外资源 启动速度 快速,通常在秒级内启动 相对较慢,通常需要数分钟 隔离级别 适度的隔离,共享内核可能存在风险 更高级别的隔离,适用于敏感工作负载 移植性 可移植,无需修改即可在不同环境中运行 需要适应不同虚拟化平台的配置和修改 生态系统 庞大的生态系统,包括Docker Hub等 相对较小的生态系统
DevOps
DevOps(Development和Operations的组合词)是一种软件开发和IT运维的文化、实践和方法论,旨在通过加强开发团队和运维团队之间的协作和自动化来加速软件开发、测试和部署过程。DevOps的目标是缩短从应用程序开发到交付的周期,提高交付质量,并确保持续交付的可靠性和可维护性。
可以实现:
-
应用更快速的交付和部署
传统:一堆帮助文档,安装程序。Docker:打包镜像发布测试,一键运行
-
更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就像搭积木一样,更简单的运维系统!
-
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多个实例。服务器的性能可以压榨到极致
Docker中的名词概念
以下是Docker的关键概念和组件:
-
Docker镜像(Image):Docker镜像是容器的构建模块,它包含了运行容器所需的一切,包括文件系统、库、依赖和配置。镜像是不可更改的,用户可以基于镜像创建容器实例。
-
Docker容器(Container):容器是从Docker镜像创建的实例,它可以运行、停止、删除和管理。每个容器都是独立的,具有自己的文件系统和运行时环境。
-
Docker仓库(Repository):Docker Hub是一个在线的镜像仓库,允许用户分享和下载Docker镜像。它包含了大量的官方和社区维护的镜像,可以用于快速构建和部署容器化应用程序。
-
Docker Compose:Docker Compose是一个工具,用于定义和运行多个容器的应用程序,以便它们可以协同工作。它使用YAML文件定义多容器应用的配置。
-
Docker Swarm:Docker Swarm是Docker的官方编排和集群管理工具,允许用户在多个主机上运行和管理容器集群。
-
Kubernetes:虽然不是Docker的一部分,但Kubernetes是一种流行的容器编排平台,用于自动化容器部署、扩展和管理。它可以与Docker一起使用,以管理大规模的容器化应用程序。
安装Docker
环境准备
-
需要会一点Linux基础
-
CentOS 7
-
使用XShell连接远程服务器进行操作
环境查看
1 | 查看系统版本 |
1 | 查看系统配置 |
安装
-
卸载
1
2
3
4
5
6
7
8yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine -
安装需要的安装包
1
yum install -y yum-utils
-
设置yum安装源
1
2
3
4(中央仓库)
yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo
(国内建议安装阿里仓库)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -
安装Docker相关的源,docker-ce社区,ee企业
1
2
3
4更新索引
yum makecache fast
更新
yum install docker-ce docker-ce-cli containerd.io -
启动Docker
1
systemctl start docker
-
使用
docker version
查看版本 -
运行hello-world
1
docker run hello-world
-
查看下载的hello-world镜像
1
docker images
-
【了解】卸载Docker
1
2
3
4依赖
yum remove docker-ce docker-ce-cli containerd.io
资源
rm -rf /var/lib/docker
阿里云镜像加速
-
找到容器镜像服务
-
点击镜像加速器
-
配置
1
2
3
4
5
6
7
8
9
10
11sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://l0s2tlrb.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
回顾hello-world执行流程
底层原理
Docker是如何工作的
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问。
DockerServer接收到Docker-Client的指令,就会执行这条命令!
为什么Docker比虚拟机快?
-
Docker有着比虚拟机更少的抽象层
-
Docker用的是宿主机的内核,VM用的是GuestOS
所以,新建一个容器的时候,Docker不需要像虚拟机 一样重新加载一个操作系统内核,避免了引导行为
Docker的常用命令
帮助命令
1 | Docker版本 |
镜像命令
-
查看镜像
1
2查看镜像
docker images1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@Joker-CentOS7 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 9c7a54a9a43c 4 months ago 13.3kB
解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATED 创建时间
SIZE 镜像的大小
可选项
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像的ID -
搜索镜像
1
2搜索镜像
docker search1
2
3
4
5
6
7
8
9
10[root@Joker-CentOS7 ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 14440 [OK]
mariadb MariaDB Server is a high performing open sou… 5510 [OK]
percona Percona Server is a fork of the MySQL relati… 619 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 860 [OK]
可选项,通过收藏过滤
--filter=STARS=3000 # 选择3000以上STAR -
下载镜像
1
2下载镜像 docker pull 镜像名[:tag]
docker pull mysql1
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
30
31
32
33
34
35
36
37
38
39
40
41
42[root@Joker-CentOS7 ~]# docker pull mysql
Using default tag: latest # 如果不写tag,默认就是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载,docker image的核心,联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 校验
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
下方两条命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest
指定版本下载
[root@Joker-CentOS7 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists # 已经存在
93619dbc5b36: Already exists # 已经存在
99da31dd6142: Already exists # 已经存在
626033c43d70: Already exists # 已经存在
37d5d7efb64e: Already exists # 已经存在
ac563158d721: Already exists # 已经存在
d2ba16033dad: Already exists # 已经存在
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7 -
删除镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17删除指定的容器:docker rmi -f [容器ID]
[root@Joker-CentOS7 ~]# docker rmi -f c20987f18b13
Untagged: mysql:5.7
Untagged: mysql@sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Deleted: sha256:c20987f18b130f9d144c9828df630417e2a9523148930dc3963e9d0dab302a76
Deleted: sha256:6567396b065ee734fb2dbb80c8923324a778426dfd01969f091f1ab2d52c7989
Deleted: sha256:0910f12649d514b471f1583a16f672ab67e3d29d9833a15dc2df50dd5536e40f
Deleted: sha256:6682af2fb40555c448b84711c7302d0f86fc716bbe9c7dc7dbd739ef9d757150
Deleted: sha256:5c062c3ac20f576d24454e74781511a5f96739f289edaadf2de934d06e910b92
删除多个指定的容器:docker rmi -f [容器ID] [容器ID] [容器ID]
[root@Joker-CentOS7 ~]# docker rmi -f c20987f18b13 9c7a54a9a43c 3218b38490ce
删除全部的容器:docker rmi -f $(docker images -aq)
其中 $(docker images -aq),是查询所有容器id
[root@Joker-CentOS7 ~]# docker rmi -f $(docker images -aq)
容器命令
-
说明:我们有了镜像才可以创建容器。我们在这里下载一个CentOS镜像来进行测试
1
[root@Joker-CentOS7 ~]# docker rmi -f $(docker images -aq)
-
运行镜像
1
docker run [参数] 镜像
参数说明
1
2
3
4
5
6
7
8
9--name="Name" #容器名字 tomcat01 tomcat02,用来区分容器
-d #后台方式运行
-t #使用交互方式运行,进入容器查看内容
-p #指定容器的端口,小写p
举例:
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
-P #随机指定端口,大写P -
进入容器
1
2
3
4启动并进入容器
[root@Joker-CentOS7 ~]# docker run -it centos bin/bash
[root@4e8db04c9471 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var -
进入当前正在运行的容器
1
2我们通常容器都是以后台方式运行的,需要进入容器,修改一些配置
docker exec -it [容器ID] [bashShell]1
2
3
4除了使用exec命令,我们还可以使用attach命令进入容器。
其区别是:exec会进入容器并开启一个新的bash终端,exit时不会导致容器stop。而attach进入会到当前正在执行的终端,不会启动新的进程,退出时会导致容器stop
docker attach [容器ID] -
退出容器
1
2停止并退出容器
[root@4e8db04c9471 /]# exit1
2容器不停止,退出。快捷键
Ctrl+P+Q -
查看容器
1
2
3
4
5
6
7
8
9
10
11
12
13查看曾经运行过的容器 docker ps 命令
列出当前正在运行的容器
-a # 列出当前正在运行的容器+带出历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号
[root@Joker-CentOS7 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e8db04c9471 centos "bin/bash" 4 minutes ago Exited (0) 2 minutes ago naughty_elion
39aa5f2ef46a 5d0da3dc9764 "bin/bash" 5 minutes ago Exited (0) 4 minutes ago gracious_borg
28f0834cf88a 5d0da3dc9764 "/bin/bash" 6 minutes ago Exited (130) 5 minutes ago brave_darwin
dc5da60f8116 9c7a54a9a43c "/hello" 46 hours ago Exited (0) 46 hours ago sleepy_hawking -
删除容器
1
2
3
4
5
6
7删除指定的容器,不能删除正在运行的服务器。强制删除 rm -f
docker rm [容器id]
删除所有的容器
docker rm -f $(docker ps -aq)
一个一个删除
docker ps -a -q|xargs docker rm -
启动或停止容器
1
2
3
4docker start [容器ID] # 启动容器
docker restart [容器ID] # 重启容器
docker stop [容器ID] # 停止当前运行的容器
docker kill [容器id] # 强制停止容器 -
从容器内拷贝文件到主机上
1
docker cp [容器ID]:[容器内路径] [目的的主机路径]
其他常用命令
-
后台启动被杀死
以后台形式启动CentOS:
1
2[root@Joker-CentOS7 ~]# docker run -d centos
d386bd6eca2f6371722797d1ab24d64e0eb517360c40b8a8fc24353c3b6f8f06会发现被强制停止了,在
docker ps
命令中找不到其id1
2[root@Joker-CentOS7 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES通过
docker ps -a
命令发现被停止了1
2
3[root@Joker-CentOS7 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d386bd6eca2f centos "/bin/bash" 40 seconds ago Exited (0) 40 seconds ago blissful_gates解释:
-
docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
-
比如Nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
-
-
查看日志
1
2
3docker logs -tf --tail [日志行数] [容器id]
-tf # 显示日志,格式化
-- tail number # 要显示的日志条数如果容器没有运行,那么就会不显示日志
-
查看容器中的进程信息
1
2top命令
[root@Joker-CentOS7 ~]# docker top [容器ID] -
查看镜像的元数据
1
2inspect命令
[root@Joker-CentOS7 ~]# docker inspect [容器ID]
总结
部署容器
部署Nginx
1 | 搜索镜像 |
部署Tomcat
1 | 官方的使用 |
1 | 进入容器 |
部署es+kibana
-
ElasticSearch
1
2
3
4
5
6
7
8ES暴露的端口非常多
ES非常耗费内存
ES的数据一般需要放置在安全目录中!挂载
--net somenetwork ? 网络配置
启动ES
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.17.131
2查看docker状态
docker status1
2修改环境 -e
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.17.13
可视化
-
portainer(先用这个)
1
2启动镜像
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /dockerData/portainer:/data --restart=always --name portainer portainer/portainer-ce:latest -
Rancher(CI/CD再用)
什么是portainer
这是一个Docker的图形化管理工具,提供一个后台面板供我们操作。可视化面板平时几乎不会使用
Docker镜像
镜像是什么
镜像是一种轻量级的、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含了运行某个软件需要的所有内容,包括代码、运行时、库、环境变量以及配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来
如何得到一个镜像:
-
从远程仓库下载
-
从别人那里拷贝
-
自己制作一个 DockerFile
Dockers镜像的加载原理
-
UnionFS 联合文件系统
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:联合加载会将各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录,实现了一次同时加载多个文件系统的持性特性,但从外部看起来,只能看到一个文件系统。
我们下载的时候看到的一层层的就是这个!
-
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统是使用UnionFS实现的。
-
bootfs(boot filesystem):bootfs是Docker镜像中的最底层,它主要包含bootloader和kernel。bootloader的主要作用是引导加载kernel。当Linux系统启动时,它会加载bootfs文件系统。在这个阶段,bootloader负责引导加载kernel。一旦kernel加载完成,整个内核就会存在于内存中。此时,内存的控制权已由bootfs转交给内核,并且系统会卸载bootfs,不再需要它的内容。
-
rootfs(root filesystem):rootfs位于bootfs之上,它包含了典型Linux系统中的标准目录和文件,如/dev、/proc、/bin、/etc等。rootfs是各种不同操作系统发行版的基础,例如Ubuntu、Centos等。当Docker容器启动时,它将加载rootfs作为容器的文件系统,从而构建容器的运行环境。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含基本的命令、工具和程序库就可以了。因为底层会直接调用Host的kernel,自己只需要提供rootfs就行。由此可见对于不同的linux发行版,bootfs基本是一致的,而rootfs有所差别,所以不同的发行版之间可以共用bootfs。
-
分层理解
我们之前下载一个镜像,可以观察到,是一层一层的下载!
1 | "RootFS": { |
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就在当前层之上,创建新的镜像层
举一个简单的例子,假如基于Ubuntu Linux 16.04 创建一个新的镜像,这就是镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层上创建第二个镜像层;如果再加入一个安全补丁,就会创建第三个镜像层。
在额外添加的镜像层的同时,镜像始终保持是当前所有层的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有不同,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看起来只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本
特点
Docker容器都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层。
commit镜像
1 | docker commit 提交容器成为一个新的副本 |
Docker容器数据卷
什么是容器数据卷
Docker的核心思想是将应用和其运行环境打包成一个镜像。然而,存在一个重要问题:当容器被删除时,其中的数据也会丢失。这引出了一个关键需求,即数据的持久性。特别是对于像MySQL这样的数据库容器,容器的删除会导致数据库丢失,这是不可接受的。因此,我们需要一种技术来实现数据的持久性,即将数据存储在本地环境中。
为满足这一需求,Docker引入了卷技术。卷技术允许容器内部产生的数据与本地环境进行同步。它通过目录的挂载实现,将容器内部的目录挂载到宿主机的Linux文件系统上。这意味着容器内部的数据可以在容器删除后保留在本地环境中,从而实现了数据的持久性和共享。这个技术在处理持久化数据和数据共享方面发挥了关键作用,使得Docker在应用开发和部署中更加灵活和可靠。
总结一句话,容器数据卷是为了方便容器的持久化和同步操作而出现的!
使用容器卷
-
方式一:使用命令来挂载
1
2
3
4docker run -it -v [主机目录]:[容器内目录]
将本机中/home/test 挂载到 Docker中centos的/home/test
docker run -it -v /home/test:/home centos /bin/bash与硬链接很相似,但是也有区别:
-
数据存储方式:
- Docker容器卷技术:Docker容器卷是一种机制,允许容器内部的数据与宿主机或其他容器之间共享或持久化。这是通过将宿主机文件系统上的目录或文件挂载到容器内部来实现的。这意味着容器内的数据可以与宿主机的文件系统交互,可以在容器之间共享数据,也可以在容器删除后保留数据。
- 硬链接:硬链接是文件系统级别的链接,允许在文件系统中创建多个指向相同数据块的引用。这些引用之间的关系是平等的,如果删除一个硬链接,不会影响其他硬链接。硬链接通常用于在文件系统中创建多个文件名引用相同的数据块。
-
用途:
- Docker容器卷技术:主要用于Docker容器内的数据管理,如持久化存储、数据共享以及容器之间的数据交换。
- 硬链接:主要用于文件系统中的文件管理,以便在不同位置使用相同的文件数据,节省存储空间。
-
适用范围:
- Docker容器卷技术:适用于容器化应用的数据管理,特别是在容器的生命周期内管理数据。
- 硬链接:适用于本地文件系统上的文件管理,通常用于减少存储占用或创建多个文件名引用相同数据的情况。
虽然Docker容器卷技术和硬链接都涉及到文件系统中的数据引用,但它们是两个不同的概念,用于不同的目的和场景。 Docker容器卷技术更加高级和复杂,涉及容器生命周期和跨容器通信,而硬链接更侧重于文件系统级别的数据共享和节省存储空间。
-
-
具名挂载和匿名挂载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21匿名挂载
-v 容器内路径!
docker run -d -P --name nginx01 -v /ect/nginx nginx
查看所有的 volume 的情况
[root@kuangshen home]# docker volume ls
DRIVER VOLUME NAME
local 9f38292179faa178afcce54d80be99d4ddd68c91d2a68870bccee72d2b7ed061
这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
具名挂载
[root@kuangshen home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@kuangshen home]# docker volume ls
DRIVER VOLUME NAME
local 95b809564484c8ac87d65c69643e7e67447f1c7ff9a91b93edec7003692e3a9
通过 -v 卷名:容器内路径
查看一下这个卷
[root@kuangshen home]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx如何区别是具名挂载还是匿名挂载,还是指定路径挂载?
-
-v 容器内路径
是匿名挂载 -
-v 卷名:容器内路径
具名挂载 -
-v /宿主机路径::容器内路径
指定路径挂载
-
-
方式二:DockerFile
Dockerfile是用来构建docker镜像的构建文件,比如一个Jar包的dockerfile如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 拉取Zulu JDK 8作为基础镜像
FROM azul/zulu-openjdk:8
# 作者
MAINTAINER sams-jar
# 设置Java启动参数
ENV JAVA_OPTS="-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
# 修复时差
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 添加jar到镜像并命名为sams.jar
ADD sams-admin.jar sams.jar
# 镜像启动后暴露的端口
EXPOSE 8080
# jar运行命令,参数使用逗号隔开
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar sams.jar"]1
2docker build -t sams-jar . # 打包成一个docker镜像
docker run -d -p 8080:8080 --add-host host.docker.internal:host-gateway sams-jar # 运行一个vite项目的dockerfile如下,同时需要配合nginx:
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 使用 nginx 作为基础镜像
FROM nginx
# 作者信息
MAINTAINER sams-ui
# 移除默认的 Nginx 配置文件
RUN rm /etc/nginx/conf.d/default.conf
# 添加自定义的 Nginx 配置文件
ADD default.conf /etc/nginx/conf.d/
# 复制前端构建文件到 Nginx 的 html 目录
COPY dist/ /usr/share/nginx/html/1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23server {
listen 80;
server_name host.docker.internal;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
location /prod-api/ {
proxy_pass http://host.docker.internal:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}1
2docker build -t sams-ui . # 打包成docker镜像
docker run -d -p 8080:80 --add-host host.docker.internal:host-gateway sams-ui # 运行
Docker网络
深入理解Docker0
宿主机使用ip addr
可以查看到如下的地址:
上述地址中docker0是docker生成的一个虚拟网卡,用来处理与容器的交互。
我们创建一个容器并尝试在容器内部运行ip addr
,可以发现容器内部除了一个默认网卡,还生成了一个eth网卡,这是docker为其生成的。同时,宿主机此时查看会多一个对应的veth网卡。
我们可以在宿主机中直接ping
此网卡的地址,是可以联通的。这意味着宿主机可以直接访问到容器内部。
这是桥接模式,使用的技术是evth-pair。每增加一个容器,宿主机增加有一个evth,容器内部增加一个eth,都是成对出现的。
容器和容器之间是可以相互连通的。
自定义网络
你可以使用docker network ls
查看所有的docker网络
说明如下:
网络模式 | 描述 |
---|---|
bridge | 默认模式,容器通过Docker桥接网络与宿主机和其他容器通信。 |
none | 不连接任何网络,完全隔离,无法与其他容器或外部网络通信。 |
host | 容器共享宿主机的网络栈,直接使用宿主机的IP和端口。 |
container | 允许容器共享另一个容器的网络栈,使用相同的IP地址。 |
我们启动容器的时候会自动拼接--net bridge
1 | docker run -d -p --name mytomcat --net bridge tomcat |
我们可以自定义一个网络
1 | docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet |
于是你会看到:
然后我们尝试在自定义的网络上创建两个容器,现在你应该可以在docker network inspect上看到。
网络联通
我们刚才创建的网络如下,它们现在是两个独立的个体,如何让Docker0中的容器访问到mynet中的?
我们可以使用connect
命令:
使用如下:
1 | docker network connect mynet tomcat01 |
结果就是将tomcat01放到了mynet网络下(一个容器两个IP)