计算机虚拟化起始于上世纪60年代的IBM公司。
虚拟化:将底层的计算机资源抽象(虚拟)为多组彼此之间互相隔离的计算平台,每个计算平台都应该具有五大基本部件中的所有设备
所有的内核在开发时都以为自己可以操作所有的硬件设备,也就是运行在环0上
1)完全虚拟化(full-virtulization)
所谓完全虚拟化,即虚拟机都不知道自己是运行在虚拟环境中的
完全虚拟化一定会导致中间有个转换的过程
2)半虚拟化(para-virtulization)
1)内存的虚拟化
2)I/O的虚拟化
1)虚拟化的两种实现方式
2)虚拟化技术的分类
1)使用brctl的配置过程
brctl add br0 # 创建br0桥 brctl stp br0 on # 开启生成树 ifconfig eth0 0 up # 要将eth0的地址删除 brctl addif br0 eth0 # 向br0上添加eth0 ifconfig br0 IP/NETMASK up # 在br0上添加IP地址 route add default gw GW # 添加默认网关
2)全手动配置
看起来ens33更像是桥,但实际上是把ens33做成交br0的桥了,引用的时候要引用br0
TYPE=Ethernet NM_CONTROLLED=no BOOTPROTO=none IPV6INIT=no NAME=ens33 DEVICE=ens33 ONBOOT=yes BRIDGE=br0 # 这块网卡桥接到br0上 USERCTL=no
TYPE=Bridge BOOTPROTO=none NM_CONTROLLED=no IPV6INIT=no NAME=br0 DEVICE=br0 ONBOOT=yes IPADDR=10.0.0.201 NETMASK=255.255.255.0 GATEWAY=10.0.0.2 DNS1=10.0.0.2 USERCTL=no
3)查看桥设备特征
# 显示当前的桥设备及桥设备的特征 brctl show
LXC(Linux Container)是一种轻量级的虚拟化手段,LXC提供了在单一可控主节点上支持多个相互隔离的server container通知执行的机制。
LXC有点像chroot,提供了一个拥有自己进程的网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化。
容器将单个操作系统管理的资源划分到孤立的组中,可以更好的平衡孤立的组之间资源使用的冲突。
docker底层使用了LXC来实现,LXC将linux进程沙盒化,使得进程之间相互隔离,并且能够控制各进程的资源分配。在LXC的基础之上,docker提供了一系列更强大的功能。
1)Docker简介
docker只是LXC的前端工具,Docker的底层就是通过LXC来实现,LXC将Linux进程沙盒化,使进程之间相互孤立,并且能够控制各进程的资源分配。
docker是一个开源的应用容器引擎,基于go语言开发。
docker可以让开发者打包到他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的linux服务器,也可以实现虚拟化。容器是完全适用沙盒机制,相互之间不会有任何接口,并且容器开销及其低。
2)docker的版本
3)虚拟机、容器、镜像
4)docker的运行方式
docker的运行方式:“分层构建 联合挂载”
一个docker启动一个进程,它就是一个普通的进程,非常方便,再挂载外部目录进行存储
大规模使用docker时必须由编排工具,因为如果有很多台服务器,为了使得资源不滥用或者过度空闲,需要将需求(业务端)和资源端(服务器)对接起来,将这个需求放到最合适的服务器上并开始构建,人是不知道哪台服务器闲置的(或者需要提前检查),编排工具就可以。一些服务启动或关闭有依赖关系(dependent),这些docker本身也无法解决,也需要编排工具来解决。如lnmp搭载的系统。
docker本质就是宿主机中的一个进程,docker是通过namespace实现资源隔离,通过cgroup实现资源限制,通过写时复制机制(copy-on-write)实现高效的文件操作(类似虚拟机的磁盘分配500G并不是占用物理磁盘500G)
1)namespace名称空间
2)Control Group控制组
1)image镜像
docker镜像含有启动容器所需要的文件系统及其内容,因此其用于创建并启动docker容器
采用分层构建机制,最底层为bootfs,其上为rootfs:
镜像的层次:
关于Aufs(advanced multi-layered unification filesystem)高级多层同一文件系统:
2)container容器
docker利用容器来运行应用,容器是从镜像创建的运行实例,它可以被启动、开始、停止、删除。
每个容器都是互相隔离的,保证安全的平台,可以把容器看做是个简易版的linux环境(包括root用户权限、镜像空间、用户空间和网络空间等)和运行在其中的应用程序。
3)repository仓库
4)图示
架构图示:
1)安装docker
配置清华大学镜像源,然后直接yum安装:
yum install docker-ce -y
注意:如果直接下载repo文件的话,需要手动修改其中的源信息,因为这个文件中是直接指向了docker官方的地址的,需要改成国内的源
2)配置镜像加速
要在 /etc/docker/daemon.json 文件中定义一个镜像加速器(这是一个json格式的数组,这个文件需要自己创建)
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
3)启动docker服务
因为docker是运行方式是C/S架构模式的,需要启动docker守护进程
systemctl start docker
1)基本信息查看
# 查看docker版本及其他信息 docker version docker info # 镜像查看 docker image ls # 查看容器信息 docker container ls docker container ls -a # 状态查看 docker ps docker ps -a # 可以查看处于停止状态的容器 # 查看网络状态 docker network ls
2)镜像的搜索和拉取
### 镜像搜索 docker search nginx:latest docker search nginx:1.16 ### 镜像的拉取和删除 # 镜像拉取 docker image pull busybox # 镜像删除 docker image rm busybox # 删除镜像 docker rmi busybox # 删除镜像 docker rm busybox # 删除容器
3)镜像的启动和停止
# 启动容器 docker start -i -a b1 # -i 交互式 # -a 依附于终端 # 创建并启动容器 # docker run可以创建并启动容器,如果没有镜像会自动去下载镜像 docker run --name b1 -i -t busybox:latest docker run --name web1 -d nginx:1.16 # -d 剥离终端 # -t 启用终端 # 停止容器 docker stop b1 # 杀死容器 docker kill b1 # 删除容器 docker rm b1 # 查看指定容器的日志 docker logs web1 # 查看容器的信息 docker inspect b1 # 在指定的容器中执行指定的命令 docker container exec -i -t web1 /bin/sh # 依附于一个启动的容器 docker attach b1 # 如果不想运行容器中给定的命令,只需在docker run后面给定命令即可 docker run --name tinyweb -it --rm -P tinyhttpd:v0.2-5 ls /data/web/html
4)从别的地址来拉取镜像
docker pull <registry>[:<port>]/[<namespace>/]<name>:<tag>
docker pull quay.io/coreos/flannel # 默认是443端口
1)运行一个busybox并做些改动
# 运行一个busybox docker run --name b1 -it busybox # 创建一个html文件并写入一些内容 vi /data/html/index.html
2)创建镜像并打上标签
# 新开一个ssh会话,创建镜像 docker commit -p b1 # -p 表示在commit的时候暂停容器 # 也可以在创建镜像的时候就打上标签 docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] # 为镜像打上标签,语法:docker tag 镜像的ID号 标签 docker tag 镜像ID dockerhgzero/httpd:v0.1 # 还可以再打个标签 docker tag hgzero/httpd:v0.1 dockerhgzero/httpd:latest
3)修改镜像启动时要运行的命令
# docker inspect 中有个Cmd的项,此项就是容器启动时要执行的命令 docker inspect dockerhgzero/httpd:latest # 修改原有基础镜像启动时要运行的命令,改Cmd就行了 docker commit -a "hgzerowzh <hgzerowzh@qq.com>" -c ‘CMD ["/bin/httpd","-f","-h","/data/html"]‘ -p b1 dockerhgzerowzh/httpd:v1.1 # docker commit 的选项: # -a 指明作者名 # -c 改动列表 # -p 制作时让其处于暂停状态 # httpd的选项: # -f 运行在前台 # -h 指明网页文件的目录
4)将镜像推送到Docker Hub
# 在推送之前要登录 # 也可以指定服务器,默认是登录Docker Hub docker login -u 用户名 -p 密码 # 推送到dockerhub docker image push dockerhgzerowzh/httpd
# 推送到阿里云 docker tag hgzerowzh/httpd:v0.1 registry.cn-qingdao.aliyuncs.com/hgzerowzh/httpd:v0.2
1)镜像的导出
docker save -o myimage.gz dockerhgzerowzh/httpd:v0.1 dockerhgzerowzh/httpd:v1.1 # -o 指明保存为一个文件 # 会自动压缩
2)镜像的导入
docker load -i myimage.gz # 使用这种方式要事先准备好本地镜像,否则执行docker run的时候它还是会到docker hub上去下载
1)Host
相当于VMware中的桥接模式,与宿主机在同一个网络中,但是没有独立的IP地址。
Docker使用了Linux的Namespace技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、iptables规则等都与其他的Network Namespace隔离。
一个Docker容器一般会分配一个独立的Network Namespace,但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机公用一个Network Namespace,容器将不会虚拟出自己动网卡、配置自己的IP等,而是使用宿主机的IP和端口。
外界访问容器中的应用,不用任何NAT转换,就如同直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
2)None
该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。
实际上,该模式关闭了容器的网络功能,在如下情况中是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)
3)Bridge
相当于VMware中的NAT模式,容器使用独立的Network Namespace,并连接到docker0的虚拟网卡(默认模式)。通过docker0网桥以及iptables nat表配置与宿主机通信。
bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
4)Container
这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。
新创建的容器不会创建自己的网卡、配置自己的IP,而是和一个指定的容器共享IP地址、端口范围等。
两个容器除了网络方面,其他的如文件系统、进程列表还是隔离的。两个容器的进程可以通过lo网卡设备通信。
1)Bridge模式的拓扑详解
当Docker Server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
接下来会为容器分配IP,Docker会从私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.0.1/16分配给docker0网桥(在主机上使用ficonfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)
2)Docker网络模式详解
Docker完成以上网络配置的过程大致是这样:
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02425f21c208 no
# 查看容器网络 docker inspect 9582dbec7981 # 查看桥设备信息 docker network inspect bridge
3)bridge模式下容器的通信
在bridge模式下,连在同一网桥上的容器可以相互通信;出于安全考虑,也可以禁止它们之间通信:在DOCKER_OPTS变量中设置 --icc=false,这样只有使用--link才能使两个容器通信。
Docker可以开启容器间通信(意味着默认配置 --icc=true),也就是说,宿主机上的所有容器可以不受任何限制的相互通信,这可能导致拒绝服务攻击;Docker可以通过--ip_forward和--iptables两个选项控制容器间、容器和外部世界的通信。
容器也可以和外部通信,主机上定义了如下iptables规则:
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE # 这条规则会将源地址为172.17.0.0/16的包(也就是从Docker容器产生的包) # 并且不是从docker0网卡发出的包,进行源地址转换,转换成主机网卡的地址 # 这样在外界看来,这个包是从主机网卡上发出来的,Docker容器对外是不可见的
1)查看网络的相关内容
# 查看网络模式 docker network ls # 查看网络的现骨干内容 docker network inspect bridge
2)docker中设置网络
docker run --name t1 -it --network bridge --rm busybox:latest --rm # 表示容器退出自动删除 --network # 指定网络类型 # none # bridge 默认 --hostname www.hgzerowzh.com # 设置主机名,注入到容器中 --dns 114.114.114.114 # 注入设置DNS --dns-search hgzerowzh.com # 向容器中注入搜索域 --add-host www.hgzerowzh.com:10.0.0.201 # 向容器中注入hosts文件解析记录
3)设置端口映射
# 将myweb容器上的80端口暴露到宿主机的随机端口(一般是3万之后) docker run --name myweb --rm -p 80 hgzerowzh/httpd:v0.2 # 可以在iptables生成的规则中查看这个随机端口 # iptables -t nat -vnl # 这条iptables规则会随着容器的删除而自动删除 # 端口映射的规则,-p选项可以使用多次 -p 80 # 将容器的80端口expose至宿主机的随机端口(一般是3万之后) # 会暴露到宿主机上所有的IP上 -p 宿主机IP::容器端口 # 将指定的容器端口映射到主机指定IP的动态端口 # 只是指定宿主机的IP地址,宿主机的端口还是随机的 -p 80:80 # 将宿主机的80端口映射到容器的80端口(前面的80表示宿主机) -p 宿主机IP:宿主机端口:容器端口 # 将宿主机指定IP的指定端口映射到容器的端口 -P # 大P表示直接暴露容器中暴露的端口 # 表示只要容器中暴露了端口,则将其直接暴露到宿主机中
1)概述
联盟式容器指用某个已经存在的网络接口的容器,接口被联盟内的各容器共享使用,因此,联盟式容器彼此间完全无隔离。
联盟式容器彼此之间虽然共享一个网络名称空间,但其他名称空间如User、Mount等还是隔离的。
联盟式容器彼此间存在端口冲突的可能性,因此,通常只会在多个容器上的程序需要程序loopback接口互相通信、或对某已存的容器的网络属性进行监控时才使用此种模式的网络模型。
2)容器之间共享网络名称空间
# 创建一个监听于2222端口的http服务容器 docker run --name b1 -d -it --rm -p 2222 busybox:latest /bin/httpd -p 2222 -f # 创建一个联盟式容器,并查看其监听的端口 docker run --name b2 -it --rm --network container:b1 buxybox:latest netstat -tan # --network container:b1 表示这个b2容器共享b1容器的网络名称空间
1)自定义docker0桥网络属性信息
{ "bip": "192.168.1.5/24", "fixed-cidr": "10.20.0.0/16", "mtu": 1500, "default-gateway": "10.20.1.1", "default-gateway-v6": "2001:db8:abcd::89", "dns": ["10.20.1.2","10.20.1.3"] } # 核心选项为bip,即bridge ip之意,用于指定docker0桥自身的IP地址
# 配置文件中最后一个key后面不能有逗号,否则语法错误
# 一般指定bip就可以了,其他选项会自动计算得知,如果希望容器的dns不使用系统的dns,也可以指定dns
2)自己创建桥
# 再创建一个网桥mybr0,地址是172.26.0.0/16,网关是172.26.0.1 docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" mybr0 # mybr0只是网络叫mybr0,网络接口的名字是 自动生成的,可以改成其他名字
docker run --name t1 -it --network mybr0 busybox:latest # 在宿主机上打开核心转发,就可以让两个网段的容器通信 # 如果ping不通,是跟iptables规则有关,被iptables阻断了而已
3)允许docker从外部连入
"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
1)文件的写时复制
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
如果运行中的容器修改了现有的一个已经存在的文件,那该文件会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制。
2)数据持久化问题
当关闭并重启容器时,其数据不受影响,但是如果删除Docker容器,则其更改将会全部丢失。
Volume与容器初始化之时就会创建,由base image提供的卷中的数据会于此期间完成复制。
Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器的时候既不会删除卷,也不会对未被引用的卷做垃圾回收操作。
3)独立于容器的数据管理机制
可以把“镜像”想成静态文件,例如“程序”,把卷类比为动态内容,例如“数据”,于是,镜像可以重用,而卷可以共享
卷实现了“程序(镜像)”和“数据(卷)”分离,以及“程序(镜像)”和“制作镜像的主机”分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境。
3)常见的服务可以分为有状态的服务和无状态的服务两种
1)Bind mount volume (绑定挂载卷)
2)Docker-managed volume (Docker管理的卷)
1)Docker管理的卷
# 将容器的/data目录映射到宿主机的docker管理的目录中 docker run -it --name bbox1 -v /data busybox # 可以使用docker inspect bbox1来查看/data在宿主机上所对应的目录位置 # 在docker inspect的Mounts建所对应的值中查看
# 过滤显示根下的Mounts中的内容 docker inspect -f {{.Mounts}} b2 # 过滤显示根下的NetworkSettings中的内容 docker inspect -f {{.NetworkSettings}} b2 # 过滤显示根下的NetworkSettings下的IPAddress中的内容 docker inspect -f {{.NetworkSettings.IPAddress}} b2 # 以上的 . 点 表示docker inspect显示内容的根
2)绑定挂载卷
# 语法:docker run -it -v HOSTDIR:VOLUMEDIR --name bbox2 busybox # 将宿主机中的/data/volumes/b2目录和容器中的/data目录做映射 docker run -it -v /data/volumes/b2:/data busybox # 默认会在宿主机上自动创建目录
3)复制使用其他容器的卷
# 创建bbox2时直接复制使用bbox1的卷 docker run -it --name bbox2 --volumes-from bbox1 busybox
1)Dockerfile
2)打包时过滤文件
可以做一个单独的隐藏文件: .dockerignore
在这个文件可以写文件路径,一行一个,可以使用通配符;在打包时,凡是在此文件中的内容,在打包时都不包含进来,包括dockerignore本身和dockerignore中定义的文件,都不会被打包进来
1)变量的定义
2)变量的引用(以下两种写法等价)
3)其他用法
${variable:-word} # 如果该变量没有值或者值为空,则将word赋值给该变量 # 如果变量有值,就用变量自身的值 ${variable:+word} # 如果变量有值,则将word赋值给该变量 # 如果该变量没有值,则不设置该变量的值
4)在docker run时,向变量传值
docker run --name web1 --rm -P -e WEB_SERVER_PACKAGE="nginx-1.15.1" tinyhttpd:v0.1-7 printenv
1)FROM
# 第一种,直接指定仓库和标签 FROM <repository>[:<tag>] # 如 FROM busybox:latest # 如果不指定tag,则默认就为latest # 第二种,指定镜像的哈希码,以防止镜像被别人冒名顶替 FROM <repository>@<digest>
2)LABEL
# 以下两种方式等价 LABEL "hgzerowzh <hgzerowzh@qq.com>" LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>"
3)COPY
COPY <src> ... <dest> # <src> 表示要复制的源文件或目录,支持使用通配符 # <dest> 表示目标路径,即真在创建的image的文件系统路径, # 建议dest使用绝对路径,否则COPY指定则以WORKDIR为其起始路径 # 如果路径中有空白字符时,可以使用如下格式 COPY ["<src>" ... "<dest>"]
4)ADD
ADD <src> ... <dest> # 或者使用如下形式 ADD ["<src>" ... "<dest>"]
5)WORKDIR
# 使用格式 WORKDIR <dir_path> # 使用示例 WORKDIR /var/log WORKDIR $STATEPATH
6)VOLUME
VOLUME <mountpoint> # 或者使用如下语法 VOLUME ["<mountpoint>"]
7)EXPOSE
EXPOSE <port>[/<protocol>][<port>[/<protocol>] ... ] # <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议 # EXPOSE指令可一次指定多个端口 EXPOSE 11211/udp 11211/tcp
8)ENV
# <key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量 ENV <key> <value> # 可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对 # 如果<value>中包含空格,可以以反斜线 \ 进行转义,也可以通过对<value>加引号进行标识 # 反斜线也可以用于续行ENV <key>=<value> ...
9)RUN
### 第一种使用语法 RUN <command> # 在这种格式中,<command>通常是一个shell命令,且以"/bin/sh -c"来运行 # 这意味着此进程在容器中的PID不为1,不能接收到Unix信号,因此,当使用docker stop命令停止容器时,此进程接收不到SIGTERM信号 ### 第二种使用语法 RUN <"executable","param1","param2"> # 在这种格式中的参数是一个JSON格式的数组,<executable>为要运行的命令,后面的<param>为传递给命令的选项或参数 # 但是这种格式指令的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行 # 如要要运行的命令依赖于此shell特性的时,可以将其替换为如下格式: RUN ["/bin/bash","-c","<executable>","<param1>"]
RUN [ "sh", "-c", "echo", "$HOME" ] # RUN产生的缓存在下一次构建的时候是不会失效的,会被重用 # 可以使用--no-cache选项,即docker build-no-cache,这样便不会缓存
基本使用示例 :
# Description: test image FROM busybox:latest #FROM busybox@哈希码 # MAINTAINER "hgzerowzh <hgzerowzh@qq.com>" LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>" ENV DOC_ROOT=/data/web/html WEB_SERVER_PACKAGE="nginx-1.15.2" COPY index.html ${DOC_ROOT:-/data/web/html/} ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/ # WORKDIR /usr/local COPY yum.repos.d /etc/yum.repos.d/ # ADD ${WEB_SERVER_PACKAGE}.tar.gz /usr/local/src/ VOLUME /data/mysql/ EXPOSE 80/tcp RUN cd /usr/local/src && tar -x nginx-1.15.2.tar.gz
10)CMD
# 下面这两种语法格式的意义同RUN
CMD <command> # 这种CMD运行命令的方式pid不为1 CMD ["<executable>", "<param1>", "<param2>"] # 这种语法格式用于为ENTRYPOINT指令提供默认参数
CMD ["<param1>", "param2"]
FROM busybox LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>" app="httpd" ENV WEB_DOC_ROOT="/data/web/html" RUN mkdir -p $WEB_DOC_ROOT && echo "<h1>Busybox httpd server.</h1>" > ${WEB_DOC_ROOT}/index.html # CMD /bin/httpd -f -h ${WEB_DOC_ROOT} CMD ["/bin/sh","-c","/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
11)ENTRYPOINT
# 跟RUN类似,在这种格式中,command通常为一个shell命令,且以"/bin/sh -c"来运行 # 此进程在容器中的PID不为1 ENTRYPOINT <command> # 跟RUN类似,这种格式指定的命令不会以"/bin/sh -c"发起,无法使用shell通配符等特性 ENTRYPOINT ["<executable>","<param1>","<param2>"]
FROM busybox LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>" app="httpd" ENV WEB_DOC_ROOT="/data/web/html/" RUN mkdir -p $WEB_DOC_ROOT && echo "<h1>Busybox httpd server.<h1>" > ${WEB_DOC_ROOT}/index.html # CMD /bin/httpd -f -h ${WEB_DOC_ROOT} CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"] ENTRYPOINT /bin/sh -c # 这样运行时会用/bin/sh -c 来运行ENTRYPOINT中的/bin/sh -c ,并且CMD中的命令将会作为参数传递给ENTRYPOINT中的指令 # 如果不想重复启用/bin/sh -c ,可以写成如下格式: # ENTRYPOINT ["/bin/sh","-c"]
实际使用示例:
FROM nginx:1.14-alpine LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>" ENV NGX_DOC_ROOT="/data/web/html" ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/ CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
#!/bin/sh # cat > /etc/nginx/conf.d/www.conf << EOF server { server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${NGX_DOC_ROOT:-/usr/share/nginx/html}; } EOF exec "$@" # 因为CMD指令中的内容将会作为参数传递给ENTRYPOINT,
# 所以当ENTRYPOINT调用此脚本文件执行完毕后,可以用exec来调用CMD指令内容中的nginx来覆盖当前进程
# 这样保证了nginx进程的PID号依然为1
12)USER
USER <UID> | <UserName> # <UID>可以为任意数字,但实践中必须为/etc/passwd中某用户的有效UID,否则docker run命令将运行失败
13)HEALTHCHECK
# 两种语法形式
HEALTHCHECK [OPTIONS] CMD command # CMD关键词后也可以跟执行shell脚本的命令或者exec数组 HEALTHCHECK NONE # 意思是禁止从父镜像继承的HEALTHCHECK生效 # OPTIONS可设定的参数(下面选项中的值都是默认值) --interval=30s # 每隔多长时间进行一次健康检查(从容器运行起来开始计时),单位s、m、h --timeout=30s # 执行command的超时时间 --start-period=0s # 启动时间,也就是在这里指定的时候之后再进行健康检查 --retries=3 # 重试次数,连续检查次数 # CMD执行完成可能的返回值 0 health状态 1 unhealth状态 2 reserved状态 # 注意:在Dockerfile中只能有一个HEALTHCHECK指令,如果列出多个,则只有最后一个生效
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
FROM nginx:1.14-alpine LABEL maintainer="hgzerowzh <hgzerowzh@qq.com>" ENV NGX_DOC_ROOT="/data/web/html" ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/ HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/ CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"]
14)SHELL
FROM microsoft/windowsservercore # Executed as cmd /S /C echo default RUN echo default # Executed as cmd /S /C powershell -command Write-Host default RUN powershell -command Write-Host default # Executed as powershell -command Write-Host hello SHELL ["powershell", "-command"] RUN Write-Host hello # Executed as cmd /S /C echo hello SHELL ["cmd", "/S", "/C"] RUN echo hello
15)STOPSIGNAL
STOPSIGNAL signal
16)ARG
ARG author=“hgzerowzh”
docker build --build-arg author=“wzh” -t myweb:v0.3-10 ./
17)ONBUILD
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dri /app/src
1)私有仓库搭建的好处
2)构建私有Registry的方式
1)安装docker私有仓库
yum install docker-registry # 安装完成后即可直接启动服务,要注意这里的是docker-distribution systemctl start docker-distribution # 安装完成后可以查看一下生成的文件 rpm -ql docker-distribution
2)配置文件
version: 0.1 log: fields: service: registry # 定义启动的服务 storage: cache: layerinfo: inmemory # 定义缓存在内存中 filesystem: rootdirectory: /var/lib/registry # 定义数据存放的位置 http: addr: :5000 # 定义监听的端口,冒号后面没写地址表示监听本机的所有地址
3)把镜像推送到刚刚建好的私有仓库
dcoekr tag myweb:v0.3-11 node1.hgzerowzh.com:5000/myweb:v0.3-11 # myweb前面没有加其他的用户名,这里表示这是一个顶层仓库 # node1.hgzerowzh.com:5000是仓库的地址
# 如果不给标签,会推送整个仓库 docker push node1.hgzerowzh.com:5000/myweb # 推送时,因为客户端使用的是https的连接,而服务端是http的响应,所以推送时会出错 docker push node1.hgzerowzh.com:5000/myweb:v0.3-11 # 仓库必须做成https的 # 如果是在内网使用,确实不想使用https,就可以在客户端添加配置,明确说明要使用非安全的docker registry
4)明确指定要使用非安全的docker-registry
# 特别注意,如下配置是要在客户端配置的,谁要连接docker-registry就在谁上配置 vim /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com"], "insecure-registries":["node1.hgzerowzh.com:5000"] # 在这里指定非安全的docker-registry }
1)harbor概述
harbor是VMwar公司基于docker registry开发的一个用于存储和分发docker镜像的企业级registry服务器。
harbor通过添加需要的功能如安全性、身份认证、管理来扩展了源Docker Distribution,提升了镜像的传输效率;harbor支持registry之间复制镜像,还提供了更高级的安全功能,比如:漏洞分析、用户管理、访问控制、活动审计等。
2)harbor的安装
harbor有两种安装方式:online installer / offline installer
online installer:从docker hub下载安装
offline installer:没有网络时,下载离线安装包安装
参考:
原文:https://www.cnblogs.com/hgzero/p/13852259.html