Dockerfile参数#
命令 | 简介 |
FROM | 设置镜像使用的基础镜像 |
MAINTAINER | 设置镜像的 |
LABEL | MAINTAINER的替代者,设置镜像的标签 |
EXPOSE | 暴露容器的端口 |
ADD | 构建镜像时,拷贝文件到容器中 |
COPY | 构建镜像时从宿主机拷贝文件到容器中 |
ENTRIPOINT | 设置容器启动后执行的命令 |
CMD | 设置容器启动后执行的命令 |
VOLUME | 设置挂载卷 |
ENV | 设置容器的环境变量 |
ARG | 设置系统的环境变量 |
USER | 设置运行RUN CMD ENTRYPOINT的用户名 |
WORKDIR | 设置RUN CMD ENTRYPOINT COPY ADD指令的工作目录 |
ONBUILD | 设置镜像的ONBUILD指令 |
STOPSIGNAL | 设置容器的退出信号量 |
FROM#
Dockerfile中的第一个非注释行,用来指定基础镜像,默认情况下会先尝试从本地获取基础镜像,本地没有的话就会去DockerHub中拉取,常用的书写格式 如下:
这是官方推荐的基础镜像地址 : https://hub.docker.com/_/alpine/
FROM image FROM image:tag FORM image:@:digest
MAINTAINER#
用来指定作者的信息,但是在未来的版本将会被弃用
LABEL#
现在官方推荐的使用LABEL去描述镜像的各种元数据,比如向下面这样,支持同时设置多个label
# Set one or more individual labels LABEL com.example.version="0.0.1-beta" LABEL vendor1="ACME Incorporated" LABEL vendor2=ZENITH\ Incorporated LABEL com.example.release-date="2015-02-12" LABEL com.example.version.is-production=""
注意上面的细节: 带空格的字符串必须加引号或空格必须转义。内部引用字符(")也必须转义
并且官方不建议上面的书写格式(因为每一条指令都会生成一个镜像),而是建议我们向下面这样合并起来label
# Set multiple labels on one line LABEL com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"
或者这样也行
# Set multiple labels at once, using line-continuation characters to break long lines LABEL vendor=ACME\ Incorporated \ com.example.is-beta= \ com.example.is-production="" \ com.example.version="0.0.1-beta" \ com.example.release-date="2015-02-12"
ADD or COPY#
ADD 和 COPY看起来很像,但是一般来说都会优先选择COPY,因为它比ADD更透明, COPY仅仅支持将本地的文件复制到容器中,使用ADD支持TAR文件和URL路径(网上文件的下载路径), 命令不能很好的却分 是从本地进行复制还是通过url从远程拉取文件
使用ADD时注意,如果是tar包的话,宿主机上的tar包拷贝到image中会被解压, 但是过URL下载链接的制作镜像时,tar包不会被自动解压, 而且容器中的目录最后需要加上/ 不然启动不起来
ENTRIPOINT or CMD#
entrypoint和cmd 都是在指定容器启动后的命令
entrypoint两种格式
ENTRYPOINT ["executable","param1","param2"] ENTRYPOINT command param1 param2 (shell中执行)
ENTRYPOINT可以指定容器启动后执行的命令,当指定多个时,同样也只有最后一个命令会生效,并且它不能被docker run中指定的参数所覆盖
(不过可以这样进行覆盖docker run命令的--entrypoint参数可以覆盖ENTRYPOINT)
cmd的三种格式
CMD ["executable","param1","param2"] # 使用exec执行 CMD command param1 param2 # 在 /bin/sh 中执行 CMD ["param1","param2"] # 给ENTRYPOINT提供默认的参数
cmd可以指定容器启动时执行的命令,每个Dockerfile中 只能有一个CMD命令,如果写了多个CMD,只有最后一个会生效, 并且,用户在通过docker run 启动容器时添加的参数 会覆盖原CMD的命令
小结:
- 他们可以指定容器启动后执行的命令,并且当同时存在多个CMD或者多个ENTRYPOINT时,只有最一个会生效
- 当Dockerfile中同时存在CMD和ENTRYPOINT时.并且CMD又不是为了给ENTRYPOINT提供默认的参数,那么谁在最后谁生效
VOLUME#
卷, 这个参数和我们启动容器时使用的docker run -v 宿主机目录:容器目录
类似这种挂载券操作, 下面命令中的挂载点其实是容器中的目录,宿主机中的目录会被随机生成
VOLUME mountpoint # 如 VOLUME /data1
举个应用的场景,当我们想将容器中mysql数据库中的数据同步到宿主机的目录下面时,我们可以使用VOLUME,这样配置后会随机在宿主机上创建一个目录存放数据
EXPOSE#
指定容器和外部进行通信的端口以及协议, EXPOSE 可以指个端口. 默认的协议是tcp协议
语法:
EXPOSE <port> EXPOSE 80/tcp 9999/udp
当我们运行镜像时,使用-p手动指定宿主机和容器的端口映射规则, 使用-P 的话,会自动完成-p的工作, 首先会自动的分配一个宿主机的端口, 然后将宿主机的端口映射到EXPOSE的端口上
ENV#
类似于环境变量,在Dockerfile中通过ENV定义的环境变量,之后可以通过$variable_name
或者{variable_name}取出值使用
两种格式:
ENV <key> <value> # 一次只能指定一对k-v ENV <kay>=<value> # 一行指定多个k-v, 如果中间有空格通过\转义,或者使用""标识, 而且\还可以表示换行
ARG#
作用和ENV相仿,都可以类型指定环境变量,而且可以在docker build创建镜像的时候,使用 --build-arg=指定参数
来指定参数
Docker 网络模型#
docker允许通过外部访问容器或者容器互联的方式提供网络服务, 安装docker deamon时,会自动安装一个docker网卡,叫做Docker0 (通多 ip addr 可以查看,如下图)
一个小例子#
在开始Docker网络的笔记前,我想说这个真实的小例子,如果你精通网络方面的知识希望你在评论区指出我说的不对的地方
**在说docker之前,我想说一个现实的例子: 我们学校想举办一场ACM区域赛,学校给了两个机房,每个机房都有一百多台电脑,老师的意思是将我们的CLP平台运行在内网中,在内网中举行这次比赛,于是我的同学开始筹划组建一个局域网,要组建一个内网,我们手里面有什么设备呢? 斐讯的路由器,还有机房的交换机. **
其实说是搭建一个局域网感觉是有点花哨了,我们的最终目的是啥呢? 其实就是让所有的同学都连接一个路由器实现电脑机房的互联(就是可以通过ip相互访问到),但是路由器上有两种接口,lanip和wanip,如果本地的机器之间想互联的话,就使用lan口, wan口是用来连接外网使用的, 路由器上面lan口就4个,两个机房中两百个机器怎么互联呢? 还好我们有交换机
**常见的内网网段: 10.X.X.X 100.X.X.X 192.168.X.X 172.16.X.X - 172.31.X.X **
下面是路由器控制台配置lan口的图片
然后大家都去连接路由器的无限信号,看上图将DHCP关掉了,连接上路由器的网络后不能不会被分配一个随机的ip使用,于是我们就得自己去手动配置自己电脑的ipv4地址,像下面这样
上面我们配置了当前的局域网中当前机器的ip地址,两个机房中的ip地址不会存在重复的情况,并且他们都能都过ip经过交换机访问到彼此
最后我们找一台虚拟机当成服务器,在上面启动Tomcat,跑我们的CLP,同学们通过ip+_端口来访问这个虚拟机上面的WebServer.就能欢快的比赛了
为什么说这个例子呢? 其实这应该就是大家说的桥接模型,整个局域网中,所有的机器想互联就得在一个网段里面,就像上面的子网掩码限制了我们的网段是192.168.1.XXX (XXX的范围是1-254),同时处于这个网段的电脑之间是可以互联的,拥有自己的ip,并且路由器如果能连接外网,那么局域网中的电脑就能中继连接外网
说了这么多和Docker有什么关系呢? docker默认的网络模型就是桥接模型, 上图中的Docker0网卡是Docker deamon的虚拟网卡, 我们可不可以将docker demon想象成他是我们虚拟机里面的一个虚拟内网呢? 这个比喻就好比是下面这样
华为云ECS == 笔记本电脑 docker deamon == VMware Workstation Pro Containner1 == VMware中的虚拟机1 Containner2 == VMware中的虚拟机2 Containner3 == VMware中的虚拟机3
就好比我们当初想让VMware中的虚拟机连接外网一样
**docker container 其实就是一个极简的linux镜像,麻雀虽小五脏俱全啊...什么dns解析,路由表,host文件它都有, 每一个docker容器模式使用桥接的网络模型就意味着没个容器都有自己的ip地址, 宿主机和容器之间怎么通信呢? 这个问题就好比你的笔记本怎么和VMare中的虚拟机如何通信一样, 可以理解成docker将物理机上的网卡虚拟化成一个交换机,进而实现彼此互联 **
有啥不懂的欢迎关注计算机网络大佬前端大佬: https://home.cnblogs.com/u/camwang
docker网络中的核心概念#
- 沙盒: Docker的沙盒可以让docker拥有完全独立的容器网络环境, 沙盒提供了端口socket,ip路由表,防火墙等内容
- 网络: 为了保证容器之间的安全通信, Docker的虚拟网络和宿主机的网络之间是隔离的,这里说的网络可以理解成docker内部的虚拟子网,Docker中的容器之间可以在这个虚拟子网中相互可见相互通信
- 端点: 容器通过这个端点实现和外网的通信,这个端点就是可控的突破封闭的网络环境的出入口
docker中存在四种网络模式 Bridge,Host,None,Containner
拓展网络模式解释:
https://www.cnblogs.com/ggjucheng/archive/2012/08/19/2646007.html
[root@139 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 0dd04b1074d6 bridge bridge local d3c5ff224f6d host host local 83a97a50d16f none null local
bridge 桥接模式#
最直观的看bridge就是, 宿主机和容器各有各的ip,但是可以互联
我们在使用docker run命令时从来没有配置过添加参数配置docker的网络模式, 那是因为docker中默认使用桥接模式网络模式, 而且,bridge模式应该是可以满足大部分的需求
我们可以是要使用bridge自定义一些网络配置
修改主机名称(就像我们常改的host文件)
[root@139 ~]# docker run --name test1 -it --network bridge -h changwu --rm busybox:latest / # hostname changwu / # cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 changwu / # cat /etc/resolv.conf # Generated by NetworkManager nameserver 100.125.1.250 nameserver 100.125.136.29 options single-request-reopen / # nslookup -type=A www.baidu.com Server: 100.125.1.250 Address: 100.125.1.250:53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com Name: www.a.shifen.com Address: 180.101.49.12 Name: www.a.shifen.com Address: 180.101.49.11 ---------命令详解------------ 在busybox容器中查看这个容器的host文件,已经修改成我在启动参数规定的值了 也就是说,当前的容器会将changwu解析成前面的ip地址 172.17.0.3 你看这个容器和linux没啥区别,确实是一个极简的linux,而且它同样有自己的dns解析配置 上面的查看resolv.conf ,100.125.1.250是外往的地址 换句话说,当前的容器访问XXX.com域名时,先找本机host文件,找不到的话,就访问这个100.125.1.250 去解析 ------参数详解-------- -h 主机名 -it 运行这个极简的bash --network 网络模式 --rm 一旦退出容器就删除该容器
自定义DNS地址
[root@139 ~]# docker run --name test -it --network bridge --dns 8.8.8.8 --rm busybox / # cat /etc/resolv.conf nameserver 8.8.8.8 options single-request-reopen -------参 数解释------- --dns 跟dns地址
更多命令使用 docker network --help 查看
**host 宿主机网络模式 **#
host网络模式和bridge桥接的区别就是 host模式中,虚拟机和主机共用一块网卡上网,这时候虚拟机和主机的之间相当于是一个机器, 容器启动后对外暴露的提供服务的端口直接绑定到注解对应的端口上, 容器的ip地址就是我的华为云ECS的公网ip
[root@139 ~]# docker run --name test -it --network host --rm busybox / # hostname 139.9X.92.X35
none#
会形成一个全封闭的容器,没有网络配置,无法和外网互联
[root@139 ~]# docker run --name test -it --network none --rm busybox / # hostname 6511ba02c5e3
container#
他和host模式很像, host模式会容器共享主机的ip, 这个container模式就是让当前容器共享另一个容器的 network namespace
[root@139 ~]# docker run --name test -it --network container:the_other_container --rm busybox