docker 容器连接, dockerfile
文章目录
- docker 容器连接
-
- 端口映射 -P/-p
- docker port 容器名:查“容器端口”对应到了“宿主机哪个地址和端口”
- Docker 容器互联
- 新建网络-d(driver):这个网络用什么网络驱动创建”
- 配置 DNS.给 Docker daemon 设置默认 DNS 服务器
-
- 把域名翻译成 IP 地址,这个东西就是 DNS。域名解析系统,把人容易记的名字,翻译成机器要用的地址
- 为什么要配置 DNS?遇到域名时,该去问谁来翻译?”
- 为什么 Docker 里经常要配 DNS?不配置 DNS容器默认继承系统或 Docker 的默认解析方式。配置 DNS你是在明确告诉 Docker:以后容器解析域名,优先去问这几个 DNS 服务器。
- dns服务器是谁配置的?怎么配置?电脑也没配置,仿佛自动可以解析
- DNS服务器怎么实现
- docker run -it --rm ubuntu cat etc/resolv.conf.开一个临时 Ubuntu 容器,看看容器内部正在使用哪个 DNS 配置
- 为什么要给容器配置DNS?给容器配置 DNS,是为了让容器能正确地把域名解析成 IP,从而正常访问软件源、网站、接口和各种网络服务。
- 手动指定容器的配置
- Docker Dockerfile
-
- 什么是 Dockerfile?文本文件,里面写的是:“怎么一步一步制作一个 Docker 镜像。”
- 指令详解
-
- COPY,从上下文目录中复制文件或者目录到容器里指定路径。
- ADD
- CMD
- ENTRYPOINT 规定“容器启动时一定要执行的主程序”.-entrypoint 覆盖 Dockerfile 里的 ENTRYPOINT
- ENV 用来在镜像里设置环境变量。ENV 会持久保留到最终镜像和容器里
- ARG 只在构建过程中可用,默认不会成为镜像里的环境变量,也不会自动出现在容器里
- VOLUME 这个目录里的数据,不要只放在容器自己身上,最好单独存出去
- EXPOSE 仅仅只是声明端口
- WORKDIR:设置容器内部的当前工作目录。类似于cd.一旦在 Dockerfile 中使用了 WORKDIR,在其之后运行的指令(如 RUN、CMD、ENTRYPOINT、COPY 和 ADD)都会在这个目录下执行.如果目录不存在,会自动创建
- HEALTHCHECK
- ONBUILD 先埋一个触发器,现在不执行,等别人拿这个镜像当基础镜像时再执行
- LABEL 给镜像贴“说明标签”
- STOPSIGNAL:设置“当 Docker 要停止容器时,先发给容器主进程的那个信号”
docker 容器连接
端口映射 -P/-p
-P:镜像里声明的端口自动映射到宿主机的随机端口
-P:把镜像里通过 EXPOSE 声明的所有端口,自动发布到宿主机的随机高位端口。Docker 官方也区分了 EXPOSE 和发布端口:EXPOSE 只是声明,真正发布到宿主机要靠 -p 或 -P

-p :[宿主机IP:]宿主机端口:容器端口[/协议]
[宿主机IP:]宿主机端口:容器端口[/协议]
如果不写宿主机 IP,Docker 默认会把端口发布到 所有网络接口,也就是通常看到的 0.0.0.0;如果写了 127.0.0.1,那就只有宿主机自己能访问;如果写了 /udp,那发布的就是 UDP 端口,不再是默认的 TCP。
TCP 和 UDP 是两套不同的端口映射。 也就是说,宿主机的 5000/tcp 和 5000/udp 不是同一个东西。




docker port 容器名:查“容器端口”对应到了“宿主机哪个地址和端口”
docker port 容器名 查看这个容器所有已经发布的端口映射

docker port 容器名 5000/docker port 容器名 5000/tcp.只看容器内部这个端口映射到了宿主机哪里

Docker 容器互联
容器命名 --name
新建网络-d(driver):这个网络用什么网络驱动创建”
-d 是 --driver,意思是:创建网络时,指定用哪一种网络驱动(network driver)。这个网络用什么网络驱动创建”。
Docker 官方说明,docker network create 里内置常见驱动有 bridge 和 overlay;如果你不写 --driver,默认会创建 bridge 网络。
bridge:一台机器里的容器网络
overlay:多台机器之间的容器网络


bridge:一台机器内部,给几个容器拉了一个局域网。同一台电脑里的容器互相连网


overlay:跨多台机器,把各台机器上的容器接成一个“虚拟大局域网”。跨多台电脑,把容器接到一个大网里


docker network create -d bridge test-net。在当前这台 Docker 主机上,建一个给容器用的本地桥接网络 test-net
配置 DNS.给 Docker daemon 设置默认 DNS 服务器

把域名翻译成 IP 地址,这个东西就是 DNS。域名解析系统,把人容易记的名字,翻译成机器要用的地址
DNS 就是把域名翻译成 IP 地址的系统;配置 DNS,就是指定“找谁来做这个翻译”。
配置 DNS 里的 IP,不是你要访问的目标地址,而是你拿来“问路”的服务器地址。
输入域名 → 问 DNS → 拿到目标 IP → 再访问网站。


为什么要配置 DNS?遇到域名时,该去问谁来翻译?”

为什么 Docker 里经常要配 DNS?不配置 DNS容器默认继承系统或 Docker 的默认解析方式。配置 DNS你是在明确告诉 Docker:以后容器解析域名,优先去问这几个 DNS 服务器。





dns服务器是谁配置的?怎么配置?电脑也没配置,仿佛自动可以解析

第一层:路由器/运营商在配

路由器,“网络总管”



电脑 → 路由器 → 运营商网络 → 互联网 → 网站服务器
第二层:公司网络管理员在配

第三层:自己手动配

DNS服务器怎么实现
DNS 服务器的实现,本质上就是一个维护“域名记录”的网络服务:它要么自己保存答案,要么按分层规则替你继续询问,最后把域名对应的结果返回给客户端。











docker run -it --rm ubuntu cat etc/resolv.conf.开一个临时 Ubuntu 容器,看看容器内部正在使用哪个 DNS 配置
-it
给你一个交互终端环境。
不过这条命令里其实不是必须,因为 cat 不是交互程序,不加通常也能跑。
–rm
容器运行结束后自动删除。
所以这是一个“一次性临时容器”。
启动一个临时 Ubuntu 容器
在容器里执行 cat etc/resolv.conf
把文件内容输出到终端
命令结束,容器自动删除

不是在 /etc/docker/daemon.json 文件 配置的吗?为什么看cat etc/resolv.conf?Docker 的容器 DNS 配置最终会映射到容器里的 resolver 配置文件
“因为 daemon.json 是配置来源,resolv.conf 是容器里的实际结果,所以要看结果文件来验证配置是否生效。”



为什么要给容器配置DNS?给容器配置 DNS,是为了让容器能正确地把域名解析成 IP,从而正常访问软件源、网站、接口和各种网络服务。




手动指定容器的配置
docker run -it --rm -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu
临时开一个 Ubuntu 容器,主机名叫 host_ubuntu,查域名优先问 114.114.114.114,短主机名默认补 .test.com
–dns 解决的是:问谁查地址
–dns-search 解决的是:遇到短名字时,自动补什么后缀。自动补域名后缀

-h 主机名,给容器起名


–dns=IP_ADDRESS: 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
etc/hosts = 把“域名或主机名”手动对应到 IP 地址的本地表





Docker Dockerfile
什么是 Dockerfile?文本文件,里面写的是:“怎么一步一步制作一个 Docker 镜像。”
它是干什么的
它告诉 Docker:
以哪个基础镜像开始
要装哪些软件
要复制哪些文件进去
工作目录设在哪
容器启动时执行什么命令





RUN:用于执行后面跟着的命令行命令。shell 格式是“让 shell 帮你执行命令”,exec 格式是“直接执行程序本身”。

shell 格式 = Docker 先启动一个 shell,然后由 shell 去解释并执行你的命令
shell 格式下,Docker 只负责启动 shell;真正解析命令字符串的是 shell。
Docker 会先启动一个 shell,再由 shell 去执行你的命令,而 exec form 不会
shell 格式是把整条命令交给 /bin/sh -c 执行,方便写 $VAR、&&、管道等 shell 语法;exec 格式是直接执行指定程序和参数,不经过 shell
shell 是命令行解释器,但不是“启动程序的唯一方式”
程序启动有两种常见路径:
路径 1:通过 shell 启动
你输入字符串命令 → shell 解析 → shell 调用系统接口启动程序
路径 2:直接启动程序
调用方已经知道程序名和参数 → 直接调用系统接口启动程序
shell 是用来解释“命令字符串”的;exec 格式已经把命令拆成了“可执行程序 + 参数数组”,所以可以直接通过操作系统的进程启动机制运行,不需要 shell 解释
Docker 的 exec 格式不经过 shell,本质上就是:Docker 不是“人在 shell 里敲一行命令”,而是程序直接告诉操作系统:
我要启动这个可执行文件:python
参数是:main.py
所以不需要 shell 帮它解释字符串
在终端里手动输入的命令,基本都是 shell 解释的。
不是所有程序启动都必须经过终端和 shell
在终端里手动执行命令时,通常都是 shell 解释;但程序启动另一个程序时,可以不经过 shell,而是直接调用操作系统接口启动目标程序。Docker 的 exec 格式就是这种方式。
当终端当前运行的是 shell 时,你输入的命令由 shell 解释;但终端本身只是输入输出界面,它也可以运行 Python、Redis CLI、MySQL CLI、Vim 等其他交互程序。
启动这些程序的那一行(Python、Redis CLI、MySQL CLI、Vim 等),通常是 shell 解释的;但是进入这些程序之后,你再输入的内容,就不是 shell 解释了。
分两阶段看最清楚。
比如你在终端输入:
python
这一行是 shell 解释的:
你输入 python
↓
shell 解析这行命令
↓
shell 找到 python 可执行文件
↓
shell 启动 Python 解释器
然后你进入 Python 交互环境:
print(“hello”)
这时候 print(“hello”) 就不是 shell 解释的了,而是 Python 解释器 解释的。
通常”,是为了避免把 终端 和 shell 说成完全等价。
更准确地说:
终端 ≠ shell
终端只是一个输入输出窗口;shell 是运行在终端里的一个程序。
一般你打开终端,系统默认会启动一个 shell,比如:
Linux/macOS: bash / zsh / sh / fish
Windows: cmd / PowerShell
所以你在终端里输入:
python main.py
大多数情况下确实是:
终端
↓
shell 接收你输入的字符串
↓
shell 解析
↓
shell 启动 python
所以可以说:人在终端里敲命令时,通常由 shell 解释。
但不是绝对,因为终端里不一定运行的是 shell。
比如你可以让终端直接运行 Python 解释器:
终端
↓
python
这时你输入的是:
print(“hello”)
解释它的就不是 shell,而是 Python。
再比如终端里运行:
redis-cli
进入 Redis 命令行后,你输入:
GET key1
解释这行命令的是 redis-cli,不是 shell。

shell格式,RUN <命令行命令>。# <命令行命令> 等同于,在终端操作的 shell 命令。


exec 格式:RUN [“可执行文件”, “参数1”, “参数2”]
exec 格式里第一个元素,一般就是要直接运行的“可执行文件”或命令。
exec 格式里,第一个元素就是要直接启动的程序,后面的元素都是传给它的参数。



Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。下载、使用、清理,尽量放在同一个 RUN 里完成






$ docker build -t nginx:v3 . 使用当前目录中的 Dockerfile 和相关文件,构建一个名为 nginx:v3 的镜像
-t nginx:v3
给构建出来的镜像打标签。
这里:
nginx 是镜像名
v3 是标签 tag

. 是构建上下文是当前目录。


上下文路径。Dockerfile 在构建时“能访问哪些本地文件”。只准用哪个目录里的材料做镜像


为什么要有这个概念?





指令详解
COPY,从上下文目录中复制文件或者目录到容器里指定路径。
COPY = 从构建可访问的来源里拿文件,复制到当前镜像阶段里;源路径看 context,目标路径看 / 和 WORKDIR,目标不存在会自动建,结尾 / 会影响它被当成文件还是目录。
如果目标以 / 开头,就是相对于镜像根目录的绝对路径;如果不以 / 开头,它就是相对于当前 WORKDIR 的相对路径。目标不存在时,Docker 会创建缺失的目录




结尾有没有 / 很重要

copy默认从 build context 复制,也可以用 --from 从 build stage、named context 或另一个 image 复制





ADD
ADD 比 COPY 多了一些“额外能力”,但正因为它会偷偷多做事,所以平时更推荐用 COPY。 Docker 官方现在的定义是:ADD 除了能从 build context 复制本地文件/目录,还能直接处理 远程 URL 和 Git 仓库;而 COPY 更“单纯”,主要就是复制文件
本地 tar 自动解压




ADD 支持从远程 URL 加文件,也支持把 Git 仓库作为源并克隆到镜像里的目标目录


CMD
CMD 是给容器设置“默认启动命令”。
如果你运行容器时没有额外指定命令,就执行它;如果你在 docker run 后面又写了别的命令,通常会把它覆盖掉。Docker 官方对 CMD 的定义就是:为执行中的容器提供默认命令,且一个 Dockerfile 里只有最后一个 CMD 生效。

CMD <shell 命令>

CMD [“可执行文件”, “参数1”, “参数2”](exec form)

CMD [“参数1”, “参数2”] 给 ENTRYPOINT 提供默认参数的

docker run 能覆盖 CMD


多个 CMD 只有最后一个生效”

ENTRYPOINT 规定“容器启动时一定要执行的主程序”.-entrypoint 覆盖 Dockerfile 里的 ENTRYPOINT
ENTRYPOINT 用来规定“容器启动时一定要执行的主程序”,而 CMD 更像是给这个主程序提供“默认参数”。 Docker 官方也是这么描述两者配合关系的:ENTRYPOINT 更适合把容器当成一个可执行程序来用,CMD 则适合给 ENTRYPOINT 提供默认参数;docker run 镜像 参数… 会覆盖 CMD,并把这些参数追加到 exec 形式的 ENTRYPOINT 后面




菜鸟应该是写错了
ENV 用来在镜像里设置环境变量。ENV 会持久保留到最终镜像和容器里
ENV 用来在镜像里设置环境变量。
设置以后,这个变量不仅能在后续的 RUN、CMD、ENTRYPOINT 等指令里用到,而且将来用这个镜像启动出来的容器里也会保留下来。




ARG 只在构建过程中可用,默认不会成为镜像里的环境变量,也不会自动出现在容器里
ARG 就是 构建时参数:它主要给 Dockerfile 的构建过程用,可以让你在 docker build 时传不同的值;但它不会像
ENV 那样自动变成运行中容器里的环境变量



VOLUME 这个目录里的数据,不要只放在容器自己身上,最好单独存出去
“挂外部存储”就是把容器里的某个目录,接到容器外面去。外面可以是你电脑上的一个真实目录,也可以是 Docker 帮你管理的一块数据区
容器里的文件,默认是跟着容器走的.重启容器:容器还是那个容器,里面原来写进去的文件通常还在. 删除容器:那个容器本身没了,写在它自己里面的数据通常也就没了




VOLUME 这个目录里的数据,不要只放在容器自己身上,最好单独存出去



“挂外部存储”就是把容器里的某个目录,接到容器外面去。外面可以是你电脑上的一个真实目录,也可以是 Docker 帮你管理的一块数据区
挂到宿主机自己指定的目录。宿主机目录:容器目录 → 你自己指定挂到本机哪里

挂到 Docker 自己管理的一块存储。这叫 volume。你不给宿主机具体目录,只给一个卷名。卷名:容器目录 → 交给 Docker 管,宿主机具体位置你通常不用管。docker volume ls 列出docker 管理的卷

VOLUME /data,它只是在镜像里声明:容器里的 /data 是个适合挂外部存储的位置。真正“外部存储挂哪里”,是在 docker run 时决定的


忘了挂载,也会自动挂匿名卷”

docker run -v 能“修改挂载点

镜像运行时,Docker 会为 /myvol 创建新 volume,并把镜像里这个位置原本已有的数据初始化到新 volume 里

EXPOSE 仅仅只是声明端口


WORKDIR:设置容器内部的当前工作目录。类似于cd.一旦在 Dockerfile 中使用了 WORKDIR,在其之后运行的指令(如 RUN、CMD、ENTRYPOINT、COPY 和 ADD)都会在这个目录下执行.如果目录不存在,会自动创建

RUN 文件系统变化会保留,shell 的“当前状态”不会保留。
RUN 的文件改动会保留到下一层,所以你 RUN mkdir /app 创建的目录,后面通常也还在。
但是你在某个 RUN 里临时 cd 到别的目录,这个“当前目录状态”不会自动延续到下一个 RUN
WORKDIR 可以写多次,而且相对路径会基于前一个 WORKDIR 继续拼。绝对路径,直接重设



HEALTHCHECK





ONBUILD 先埋一个触发器,现在不执行,等别人拿这个镜像当基础镜像时再执行
ONBUILD 是在当前 Dockerfile 构建完成之后,当该镜像被别的 Dockerfile FROM 时才执行
LABEL 给镜像贴“说明标签”



STOPSIGNAL:设置“当 Docker 要停止容器时,先发给容器主进程的那个信号”



信号(signal)就是操作系统发给进程的一种“通知”






更多推荐







































所有评论(0)