Docker入门篇
Docker概述
docker官网:https://www.docker.com/
文档:https://docs.docker.com/ Docker的文档是超级详细的!
仓库:https://hub.docker.com/
Linux Container容器(LXC)是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。
- 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以轻便
- 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
Docker的基本组成
Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就是 image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。类似Java中的类。
Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。类似Java中类的实例化。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
仓库注册服务器(Registry)上往往存放着多个仓库(Repository),每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库(Repository)是集中存放镜像文件的场所。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等
Docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。
Docker的工作流程如下:
- 用户使用Docker客户端执行命令,例如创建容器或构建镜像。
- Docker客户端将命令发送给Docker守护程序。
- Docker守护程序根据命令执行相应操作,可能需要下载或从本地存储中加载镜像。
- Docker守护程序创建容器实例并运行应用程序。
- 容器与宿主系统共享内核,但有自己的文件系统和进程空间,因此可以隔离运行。
- 用户可以使用Docker客户端来管理容器的生命周期,包括启动、停止、删除等操作。
- Docker守护程序还可以与Docker仓库通信,以获取新的镜像或将本地构建的镜像推送到仓库。
为什么Docker比Vm快
Docker 比传统虚拟机(VM)快的主要原因在于容器化技术的设计和实现方式与虚拟机不同,导致了更轻量级、更高效的性能。
以下是 Docker 相对于传统 VM 的速度优势的主要原因:
- 共享内核: Docker 容器与宿主系统共享相同的操作系统内核,而传统虚拟机需要在每个 VM 中运行独立的操作系统。由于共享内核,容器比虚拟机更轻量级。这意味着容器不需要启动整个操作系统,只需加载应用程序和其依赖项。虚拟机则需要模拟整个操作系统,包括内核,这会占用更多的资源和时间。
- 更少的资源消耗: 由于容器共享内核,它们在内存和计算资源方面要求较少。虚拟机需要分配大量的内存和CPU资源来模拟完整的操作系统。这意味着在相同硬件上可以运行更多的容器实例,从而提高了资源利用率。
- 更快的启动时间: 由于容器是轻量级的,它们的启动速度非常快。通常,容器可以在几秒钟内启动,而虚拟机可能需要几分钟来启动。这对于弹性扩展和快速部署非常有用。
- 更少的虚拟化开销: 虚拟机需要额外的虚拟化层来模拟硬件和操作系统,这会引入额外的性能开销。容器化使用了更轻量级的虚拟化技术,减少了这种开销。
- 更好的资源管理: Docker 提供了先进的资源管理和隔离机制,允许您精确地控制容器使用的资源。这可以确保不同容器之间的资源不会相互干扰,并允许更好地利用物理资源。
Docker容器 | 虚拟机(VM) | |
---|---|---|
操作系统 | 与宿主机共享OS | 宿主机OS上运行虚拟机OS |
存储大小 | 镜像小,便于存储和传输 | 镜像庞大(vmdk,vdi等) |
运行性能 | 几乎无额外性能损失 | 操作系统额外的CPU,内存消耗 |
移植性 | 轻便,灵活,适应于Linux | 笨重,与虚拟化技术耦合度高 |
硬件亲和度 | 面向软件运维者 | 面向硬件运维者 |
部署速度 | 快速,秒级 | 较慢,10以上 |
Docker常用命令
帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/
1 | docker version #显示docker的版本信息。 |
镜像命令
1 | #查看所有本地主机上的镜像 可以使用docker image ls代替 |
docker images
列出本地主机上的镜像显示说明:
1
2
3
4
5
6
7
8
9
10REPOSITORY:表示镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,
docker 将默认使用 ubuntu:latest 镜像OPTIONS说明:
1
2
3
4-a :列出本地所有的镜像(含中间映像层)
-q :只显示镜像ID。
--digests :显示镜像的摘要信息
--no-trunc :显示完整的镜像信息
docker search 某个XXX镜像名字
从网站:https://hub.docker.com 上查找
命令:
docker search [OPTIONS] 镜像名字
OPTIONS说明
1
2
3--no-trunc : 显示完整的镜像描述
-s : 列出收藏数不小于指定值的镜像。
--automated : 只列出 automated build类型的镜像;
docker pull 某个XXX镜像名字
下载镜像docker pull 镜像名字[:TAG]
docker rmi 某个XXX镜像名字ID
删除镜像删除单个:
docker rmi -f 镜像ID
删除多个:
docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部:
docker rmi -f $(docker images -qa)
容器命令
有镜像才能创建容器,这是根本前提(下载一个CentOS镜像演示
docker pull centos
)1
2
3
4
5
6
7
8
9
10
11
12
13
14# 新建容器并启动
docker run 镜像id
# 列出所有运行的容器 docker container list
docker ps
# 删除指定容器
docker rm 容器id
# 启动容器
docker start 容器id
# 重启容器
docker restart 容器id
# 停止当前正在运行的容器
docker stop 容器id
# 强制停止当前容器
docker kill 容器id
新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS说明(常用):有些是一个减号,有些是两个减号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15--name="容器新名字": 为容器指定一个名称;
-d: 后台运行容器,并返回容器ID,也即启动守护式容器;
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--rm 当退出时删除运行的容器
-P(大写): 随机端口映射;
-p: 指定端口映射,有以下四种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
启动交互式容器
docker run -it centos /bin/bash
- 默认使用镜像centos:latest,-it 以交互模式启动一个容器,在容器内执行/bin/bash命令。
列出运行的容器
docker ps [OPTIONS]
OPTIONS说明(常用):
1
2
3
4
5-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
--no-trunc :不截断输出。
退出容器
- 两种退出方式
exit
,容器停止退出ctrl+P+Q
容器不停止退出
启动容器
docker start 容器ID或者容器名
重启容器
docker restart 容器ID或者容器名
停止容器
docker stop 容器ID或者容器名
强制停止容器
docker kill 容器ID或者容器名
删除已停止的容器
docker rm 容器ID
一次性删除多个容器
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
容器命令2
启动守护式容器
后台启动命令
docker run -d 容器名
,容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。启动一个centos容器
1
2#使用镜像centos:latest以后台模式启动一个容器
docker run -d centos然后
docker ps -a
进行查看, 会发现容器已经退出,说明很重要的一点: Docker容器需要后台运行,就必须有一个前台进程。比如你web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如
service nginx start
, 但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用, 就会立刻停止。最佳的解决方案是将你要运行的程序以前台进程的形式运行。添加前台进程
1
docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done"
查看容器日志
docker logs -f -t --tail 容器ID
1
2
3# -t 加入时间戳 -f 跟随最新的日志打印
-tf #显示日志信息(一直更新)
--tail # 数字显示最后多少条示例
1
2docker logs -t --tail n 容器id #查看n行日志
docker logs -tf 容器id #显示日志信息
查看容器内运行的进程
- 类似在容器中使用ps命令 。
docker top 容器ID
查看容器内部细节
docker inspect 容器ID
1
2
3
4
5
6
7
8
9
10
11# 查看镜像的元数据
docker inspect 55321bcae33d
[
{
"Id":
"55321bcae33d15da8280bcac1d2bc1141d213bcc8f8e792edfd832ff61ae5066",
"Created": "2020-05-15T05:22:05.515909071Z",
"Path": "/bin/sh",
...
}
]
交互式进入运行的容器
常容器都是使用后台方式运行的,需要进入容器,修改一些配置可以使用
1 | docker exec -it 容器id shell # 有 /bin/bash /bin/sh |
上述两个区别:
exec
是在容器中打开新的终端,并且可以启动新的进程(常用)attach
直接进入容器启动命令的终端,不会启动新的进程
容器内拷贝文件到主机上
1 | docker cp 容器ID:容器内路径 目的主机路径 |
镜像命令
1 | docker commit 提交容器成为一个新的副本 |
Docker命令帮助文档
命令 | 备注 | 说明 |
---|---|---|
attach | Attach to a running container | 当前 shell 下 attach 连接指定运行镜像 |
build | Build an image from a Dockerfile | 通过 Dockerfile 定制镜像 |
commit | Create a new image from a container changes | 提交当前容器为新的镜像 |
cp | Copy files/folders from the containers filesystem to the host path | 从容器中拷贝指定文件或者目录到宿主机中 |
create | Create a new container | 创建一个新的容器,同 run,但不启动容器 |
diff | Inspect changes on a container’s filesystem | 查看 docker 容器变化 |
events | Get real time events from the server | 从 docker 服务获取容器实时事件 |
exec | Run a command in an existing container | 在已存在的容器上运行命令 |
export | Stream the contents of a container as a tar archive | 导出容器的内容流作为一个 tar 归档文件[对应 import ] |
history | Show the history of an image | 展示一个镜像形成历史 |
images | List images | 列出系统当前镜像 |
import | Create a new filesystem image from the contents of a tarball | 从tar包中的内容创建一个新的文件系统映像[对应export] |
info | Display system-wide information | 显示系统相关信息 |
inspect | Return low-level information on a container | 查看容器详细信息 |
kill | Kill a running container | kill 指定 docker 容器 |
load | Load an image from a tar archive | 从一个 tar 包中加载一个镜像[对应 save] |
login | Register or Login to the docker registry server | 注册或者登陆一个 docker 源服务器 |
logout | Log out from a Docker registry server | 从当前 Docker registry 退出 |
logs | Fetch the logs of a container | 输出当前容器日志信息 |
port | Lookup the public-facing port which is NAT-ed to PRIVATE_PORT | 查看映射端口对应的容器内部源端口 |
pause | Pause all processes within a container | 暂停容器 |
p | List containers | 列出容器列表 |
pull | Pull an image or a repository from the docker registry server | 从docker镜像源服务器拉取指定镜像或者库镜像 |
push | Push an image or a repository to the docker registry server | 推送指定镜像或者库镜像至docker源服务器 |
restart | Restart a running container | 重启运行的容器 |
rm | Remove one or more containers | 移除一个或者多个容器 |
rmi | Remove one or more images | 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除] |
run | Run a command in a new container | 创建一个新的容器并运行一个命令 |
save | Save an image to a tar archive | 保存一个镜像为一个 tar 包[对应 load] |
search | Search for an image on the Docker Hub | 在 docker hub 中搜索镜像 |
start | Start a stopped containers | 启动容器 |
stop | Stop a running containers | 停止容器 |
tag | Tag an image into a repository | 给源中镜像打标签 |
top | Lookup the running processes of a container | 查看容器中运行的进程信息 |
unpause | Unpause a paused container | 取消暂停容器 |
version | Show the docker version information | 查看 docker 版本号 |
wait | Block until a container stops, then print its exit code | 截取容器停止时的退出状态值 |
Docker可视化
portainer是Docker图形化界面管理工具!提供一个后台面板供我们操作!
1 | # 运行如下命令即可 打开可视化服务 |
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.
镜像为什么采用分层结构?
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之
上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在
该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层。在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,上层镜像层中的文件可以覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统
一的文件系统。Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的文件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。
Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层
和CoW 。
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层!最大的好处,莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了。
Docker数据管理
Docker的理念是将运用与运行的环境打包形成容器运行,Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。为了能保存数据在docker中我们使用卷,提出了容器数据卷。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
数据卷可在容器之间共享或重用数据
卷中的更改可以直接生效
数据卷中的更改不会包含在镜像的更新中
数据卷的生命周期一直持续到没有容器使用它为止
1 | # 查看所有的volume的情况 |
三种挂载: 匿名挂载、具名挂载、指定路径挂载
1 | # 三种挂载: 匿名挂载、具名挂载、指定路径挂载 |
命令挂载卷 -v
官方建议用映射目录的方式来互相同步修改。
1 | --volume -v # 绑定挂载卷 |
卷权限说明
不指定(默认): 权限同rw
ro
(readonly 只读)- 文件:容器内不能修改,会提示read-only
- 文件夹:容器内不能修改、新增、删除文件夹中的文件,会提示read-only
rw
(readwrite 可读可写)- 文件:
- 不管是宿主机还是容器内修改,都会相互同步;
- 但容器内不允许删除,会提示Device or resource busy;
- 宿主机删除文件,容器内的不会被同步
- 文件夹:不管是宿主机还是容器内修改、新增、删除文件,都会相互同步
1
2docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx- 文件:
具名和匿名挂载
匿名挂载:
-v
只写了容器内的路径,没有写容器外的路径1
2
3
4
5
6
7# 匿名挂载 -v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
docker volume ls
DRIVER VOLUME NAME
local 83a7785666d2612ea6b7ace391743306a5c63e0f913c5c7942de717c42009d9e具名挂载:
-v 卷名:容器内路径
1
2
3
4
5
6docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 查看所有的volume的情况
docker volume ls
DRIVER VOLUME NAME
local juming-nginx
卷路径
查看一下juming-nginx这个卷的信息
1
2
3
4
5
6
7
8
9
10
11
12[root@k8s-master01 ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2023-09-08T16:48:48+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]所有的docker容器内的卷,没有指定目录的情况下都是在
/var/lib/docker/volumes/xxxx/_data
下如果指定了目录,
docker volume ls
是查看不到的
Docker磁盘空间清理
查看 Docker 的磁盘使用情况:
1 | # 类似于 Linux上的 df 命令 |
容器清理
1 | # 仅删除停止运行的容器。 |
镜像清理: 有一些镜像是隐形的:
子镜像,就是被其他镜像引用的中间镜像,不能被删除。
悬挂状态的镜像,就是不会再被使用的镜像,可以被删除。
1 | # 通过镜像的id来删除指定镜像。 |
数据卷清理
1 | # 删除不再使用的数据卷 |
缓存清理: Docker 18.09 引入了 BuildKit ,提升了构建过程的性能、安全、存储管理等能力。
1 | # 删除 build cache。 |
一键清理: 注意,这两个命令会把你暂时关闭的容器,以及暂时没有用到的 Docker 镜像都删掉了。
1 | # 可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像) |
初识Dockerfile
dockerfile 是用来构建docker镜像的文件!命令参数脚本!
基础知识
- 每个保留关键字(指令)都是必须是大写字母
- 执行从上到下顺序
#
表示注释- 每一个指令都会创建提交一个新的镜像层,并提交!
DockerFile指令
保留字 | 说明 |
---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的 |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 容器构建时需要运行的命令 |
EXPOSE | 当前容器对外暴露出的端口 |
WORKDIR | 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点 |
ENV | 用来在构建镜像过程中设置环境变量 |
ENV MY_PATH /usr/mytest,这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,比如:WORKDIR $MY_PATH | |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 |
COPY | 类似ADD,拷贝文件和目录到镜像中(不会自解压)。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置COPY [“src”, “dest”] |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | 指定一个容器启动时要运行的命令 |
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 | |
ENTRYPOINT | 指定一个容器启动时要运行的命令,ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数 |
ONBUILD | 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发 |
自定义centos镜像
构建步骤:
编写一个dockerfile文件
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#获取国内源
curl -o CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
vim mydockerfile-centos
#继承自哪个镜像
FROM centos:7
#作者和邮箱
MAINTAINER fl_6145<fl_6145@163.com>
#使用 ADD 命令将 CentOS-Base.repo 拷贝到目标基础镜像的目录下
ADD CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo
#运行yum makecache生成缓存,便于查找
RUN yum makecache
#自定义环境变量
ENV mypath /usr/local
#登录容器后的落脚点
WORKDIR $mypath
#登录容器后执行的安装命令
RUN yum -y install vim
RUN yum -y install net-tools
#向外暴露的端口
EXPOSE 80
#容器运行后执行的命令
CMD echo "-----end----"
CMD /bin/bashdocker build 构建称为一个镜像, 最后的
.
表示当前目录1
docker build -f mydockerfile-centos -t mycentos:0.1 .
docker run运行镜像
1
docker run -it mycentos:0.1
docker push发布镜像(DockerHub 、阿里云仓库)
CMD/ENTRYPOINT
都是指定一个容器启动时要运行的命令
1
2
3
4
5
6
7
8
9vim dockerfile-test-cmd
FROM centos
CMD ["ls","-a"]
# 构建镜像
docker build -f dockerfile-test-cmd -t cmd-test:0.1 .
# 运行镜像
docker run cmd-test:0.1Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
1
2
3
4
5
6# cmd的情况下 -l 替换了CMD["ls","-l"]。
# -l 不是命令所有报错
docker run cmd-test:0.1 -l
# 如果要ls -al
docker run cmd-test:0.1 ls -aldocker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合(追加)
1
2
3
4
5
6
7
8
9
10
11# 编写dockerfile文件
vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建镜像
docker build -f dockerfile-test-entrypoint -t entrypoint-test:0.1 .
# 运行镜像
docker run entrypoint-test:0.1
# 追加命令 ls -a -l
docker run entrypoint-test:0.1 -l
发布自己的镜像
这里使用阿里云:创建镜像仓库 centos
- 登录阿里云Docker Registry
1 | # 用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。 |
- 从Registry中拉取镜像
1 | $ docker pull registry.cn-hangzhou.aliyuncs.com/fulsun/centos:[镜像版本号] |
- 将镜像推送到Registry
1 | $ docker login --username=***** registry.cn-hangzhou.aliyuncs.com |
Docker网络
安装Docker时,它会自动创建三个网络,默认bridge
网桥(创建容器默认连接到此网络)、 none
、host
1 | # 查看docker网络 |
网络驱动模型
bridge
:Docker中默认的网络驱动模型,在启动容器时如果不指定则默认为此驱动类型;host
:打破Docker容器与宿主机之间的网络隔离,直接使用宿主机的网络环境,该模型仅适用于Docker17.6及以上版本;overlay
:可以连接多个docker守护进程或者满足集群服务之间的通信;适用于不同宿主机上的docker容器之间的通信;macvlan
:可以为docker容器分配MAC
地址,使其像真实的物理机一样运行;none
:即禁用了网络驱动,需要自己手动自定义网络驱动配置;plugins
:使用第三方网络驱动插件;
在使用
docker run
创建Docker容器时,可以用--net
选项指定容器的网络模式,
Docker可以有以下4种网络模式:
host模式
:使用--net=host
指定。none模式
:使用--net=none
指定。bridge模式
:使用--net=bridge
指定,默认设置。container模式
:使用--net=container:NAME_or_ID
指定。
1 | docker run -it -P --name tomcat01 --net=bridge tomcat # 默认设置 |
容器通信问题
容器在默认情况下以隔离方式运行,它们完全不知道同一计算机上有其他进程或容器。 那么,如何使容器能够彼此通信? 答案就是网络连接。 如果两个容器在同一网络上,那么它们可彼此通信。 如果没在同一网络上,则没法通信。
- 由于不同容器通过
veth pair
连接在虚拟网桥docker0
上,所以容器之间可以通过IP
互相通信,但是docker0无法通过容器名进行通信。 - 为了实现不同容器通过容器名或别名的互连,docker提供了以下几种:👇
- 在启动docker容器时加入
--link
参数,但是目前已经被废弃,废弃的主要原因是需要在连接的两个容器上都创建–link选项,当互连的容器数量较多时,操作的复杂度会显著增加; - 启动docker容器后进入容器并修改
/etc/hosts
配置文件(本地DNS解析),缺点是手动配置较为繁杂; - 用户自定义bridge网桥,这是目前解决此类问题的主要方法,提供更好的隔离效果和更好的互通性(更好的隔离效果是针对外界网络,而更好的互通性则是指同一
bridge
下的不同容器之间),用户自定义bridge在容器之间提供了自动DNS解析。
- 在启动docker容器时加入
Docker0
该
bridge
网络代表docker0
,所有Docker安装中存在的网络。除非你使用docker run --network=<NETWORK>
选项指定,否则Docker守护程序默认将容器连接到此网络查看默认bridge网桥(docker0)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46[root@docker-node01 ~]# docker network inspect ac13ae33e4ad
[
{
"Name": "bridge",
"Id": "ac13ae33e4ad0fb6e7f0f0b0323d1c02b16f7bd01cd388c58be8bbecf3f873ca",
"Created": "2023-09-09T16:45:29.969100643+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"1472199ffd7beb82b3b3d9f2dfd025eddfc3a2f22c568a7dcfbf801bc75f084c": {
"Name": "tomcat01",
"EndpointID": "4efab10676b37e424e2c184beca375fdfc91573662a97871be7da5e91db0999c",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]启动时,docker默认的bridge网桥,docker0给容器服务自动分配ip
1
2docker run -it --name centos01 centos /bin/bash
docker run -it --name centos02 centos /bin/bash查看运行容器的ip
docker inspect 容器ID | grep IPAddress
查看查看宿主机网络,发现docker分配了 77、79 的ip地址
此时,进入centos01容器,ping centos02容器的ip可以ping通,但是ping不通容器名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19[root@0043c61be833 /]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.128 ms
# docker0不支持容器名连接访问
[root@0043c61be833 /]# ping centos02
ping: centos02: Name or service not known
# 查看容器的网卡 发现是76
[root@0043c61be833 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
76: eth0@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
容器通信原理
- 只要我们安装了docker,就会有一个网卡docker0(相当于一个路由器),每启动一个docker容器,docker都会给docker容器分配一个ip(连接路由器的终端,同一网段下终端可以互相通信),
- 通过
evth-pair
技术实现,evth-pair
就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连,evth-pair
充当一个桥梁,连接各种虚拟网络设备。 - Docker网络使用的是
Linux桥接
,宿主机是docker容器的网桥,docker0最多分配65535个 - 删除容器之后,虚拟网卡就自动消失了。(虚拟网卡传递效率高!)
- 启动容器不设置网络,容器ip由docker0自动分配情况下,容器间的通信,要经过
evth-pair
技术实现,并不是直连的。(跟计算机网络通信类似,分层模型,TCP/IP协议数据报封装解封装)
–link
上面docker0
不支持容器名连接访问,容器通信只可以通过容器ip
通信,docker也无法保证容器重启后的IP地址不变,可通过--link
建立连接别名进行互联(官方不推荐使用)
原理分析:
- 运行容器时,指定参数link,使得源容器与被链接的容器可以进行相互通信,并且接受的容器可以获得源容器的一些数据,比如:环境变量。
- 与/etc/hosts中的主机条目不同,如果重新启动源容器,则不会自动更新存储在环境变量中的IP地址。我们建议使用主机条目 /etc/hosts来解析链接容器的IP地址。
- 除了环境变量之外,Docker还将源容器的主机条目添加到/etc/hosts文件中。(本质上就是通过 –link 参数,自动的给容器添加 hosts 配置)
建立连接步骤:✨
1 | # 启动tomcat01 |
用tomcat03 ping tomcat02 可以ping通
用tomcat02 ping tomcat03 ping不通
1 | # tomcat02 容器link 到 tomcat03 上 |
自定义网络
1 | Usage: docker network COMMAND |
查看所有的docker网络
1 | [root@docker-node01 ~]# docker network ls |