Dokcer入门及其Docker file的制作指令
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dokcer入门及其Docker file的制作指令相关的知识,希望对你有一定的参考价值。
Docker借鉴了kvm中应用镜像的方式,使得Docker的出现方便了容器的实现和使用,从此docker就占据了容器的市场。
docker:引擎:创建、运行容器,采用C/S架构
客户端:docker
服务端:dockerd,dockerd负责接收docker客户端的请求,客户端发送指令,dockerd通过镜像仓库,把镜像拖到本地,执行运行容器
容器是基于镜像启动的,如果本地没有镜像,dockerd会去远程拉取镜像。
IT行业的部署异构化程度越来越大。不同的开发平台,不同的运行平台,各个服务不同的需求环境。此时我们不必再根据不同的底层运行平台部署不同的运行环境。但是有了docker之后,只需保证能在docker上运行就可以,而不同的环境只要能运行docker就可以。
docker后来把lxc换成了libcontainer。
docker并没有解决容器之间的编排工具,google的kubernetes解决了这个问题。
容器提供的镜像包含了应用的所有依赖项,因而从开发到测试、生产环境中都有可移植性。
容器技术起源于FreeBSD jail,jail 的目的是让进程在经过修改的 chroot 环境中创建,而不会脱离和影响整个系统 — 在 chroot 环境中,对文件系统、网络和用户的访问都实现了虚拟化。尽管 Jail 在实施方面存在局限性,但最终人们找到了脱离这种隔离环境的方法。
镜像文件存储于Registry仓库中,镜像文件是分层构建的,所以其文件系统必需为分层文件系统(aufs,overlafs)
docker可以通过一个镜像文件启动多个容器,镜像是只读的,每一个容器都在镜像上层建立了一层内部可写的专用层,所有读写都仅在自己的专用层上实现。
Registry:一个镜像仓库服务器,可以通过一个套接字接受镜像的搜索和下载请求。镜像存储于Registry后面的存储空间中,可以有很多仓库,每一个仓库只放一种镜像,其中的每一个镜像都有其对应的tag(标签)。Registry对每一个仓库和镜像有一个索引,还有用户的账户密码,对仓库进行认证和管理。
每一个容器内可以允许多个进程、线程,但docker中每一个容器内部只运行一个进程及其子进程,只要次进程停止,则该容器也停止了。容器内进程运行的日志被送到控制台,这样查看日志的时候就不需要进入容器内部,只需在控制台查看。容器管理被简化。
Registry:通过一个httpd服务器提供服务,https为Registry,http为insecure Registyry
Registry可以自定义,也可以使用官方提供的
docker image
采用分层构建机制,最底层为bootfs,其之为rootfs
bootfs:用于系统引导的文件系统,包括BootLoader和kernel,容器启动完成后会被卸载以节约内存资源;
rootfs:位于bootfs之上,表现为docker容器的根文件系统;
传统模式中,系统启动之时,内核挂载rootf时会首先将其挂载为只读,完整性自检完成后将其重新挂载为读写
docker中,rootfs由内核挂载为只读模式,而后通过联合挂载技术额外挂载一个“可写”层。
位于下层的镜像称为父镜像,最底层的称为基础镜像
最上层为“可读写”层,其下的为“只读”层
automated builds:docker hub可以根据用户上传的指令制作docker镜像
webhooks:docker hub可以根据git服务器上代码的变化而自动制作镜像
制作镜像
制作镜像的时候只需要把最上面的可写层修改后保存。后续调用此镜像的时候,分层挂载系统会自动把基础镜像给挂载上去
运行为容器之后因为只有一个进程,所以就不可能通过systemd来管理各个进程了。
docker save httpd:v0.1 centos7:v0.1 /data/centos-httpd.tar 通过docker save把本机的image保存至一个tar文件,通过scp等命令把tar文件传输到目标主机上
docker load -i centos-httpd.tar 根据tar文件解压镜像到本地
docker container commit -a "zhanghw" -c ‘CMD ["/bin/sh","-c","/bin/httpd -h var/www/html -f"]‘ -p b1 tiny-httpd:v5
以正在运行的image为基础,用命令修改镜像启动后的首个进程。
docker 启动时显示:bridge-nf-iptables is disabled 解决方法
vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
让docker可以自动设定iptables
docker network
三种内建虚拟网络:none,bridge,host
四种网络类型
closed container:没有外网接口,只要lo网卡
bridged container:一个lo网卡,一个桥接网卡
united container:网卡由两块网卡共用,共用同一个TCP/IP 协议栈
open container:直接使用host的物理网卡
docker run --name a1 -it --network none httpd:2.4
--network none 设置其网络为:closed container
--network bridge 设置其网络为:bridged container
--network container:a1 设置其网络为:united container
--network host 设置其网络为:open container
docker -p 发布服务,暴露服务
把一个容器内的网络暴露到外部,让外部网络可以访问容器内的服务
hostIP:hostPort ---> conIP:conPort PNAT机制实现
在创建容器的时候使用-p选项指定
-p conPort 主机端口随机指派
-p conPort:hostPort 指定主机端口
-p hostIP::conPort 指定主机IP,::之间为主机端口,不指定为随机获取
-p hostIP:hostPort:conPort 指定主机的IP和端口
docker port continer 查看容器暴露端口的情况
docker network create
docker network create -d bridge --gateway 192.168.1.1 --subnet 192.168.1.0/24 vmnet1
docker run --network create container 通过--network指定多个网络时,只有最后一个生效
docker network connect bridge vmnet1 c1 把c1连接至vmnet1
docker network disconnect vmnet1 c1 剥离网络
docker network rm vmnet1 删除网络
docker inspect host 查看网络定义
docker network inpect -t
create:根据指定信息创建网络
docker network create -h 查看帮助
docker network create -d bridge --gateway 192.168.1.1 --subnet 192.168.1.0/24 vmnet1
docker container run --name a1 --network vmnet1 -it --rm busybox:latest 启动容器时指定其网络
docker network connect bridge a1 吧container a1 连接到bridge网络上
Data volume
可写层依存于下一层镜像,docker commit 是根据最上层镜像的变化来创建镜像的,其底层的镜像通过联合挂载技术实现。
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
写时复制(cow):如果一个文件需要修改,则会把在底层中的文件复制到最上面的可写层,联合挂载系统此时会屏蔽最下面只读层中的文件,只显示可写层中的文件。
大量业务数据不建议直接存储在容器镜像中:
1.多层镜像读写性能差。
2.容器一删除,其保存的文件也被删除
3.磁盘的IO读写一直是服务器整体性能的瓶颈
卷:容器上的一个或多个目录,此类目录可绕过联合文件系统,与宿主机上的某个目录关联。独立于容器的生命周期实现数据持久化,实现数据和运行程序分离。
?Volume于容器初始化之时即会创建,由base image提供的卷中的数据会于此期间完成复制
? Data volumes can be shared and reused among containers
? Changes to a data volume are made directly
? Changes to a data volume will not be included when you update an image
? Data volumes persist even if the container itself is deleted
?Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时既不会删除卷,也不会对哪怕未被引用的卷做垃圾回收操作
Docker支持两种类型的存储卷
1.动态:container上指定存储卷,但至于对应的宿主机中的文件路径则是docker-daemon随机产生的,也称之为docker管理的卷。
2.静态:container上指定、宿主机上对应的卷也由用户手动指定。
?为docker run命令使用-v选项即可使用Volume
? Docker-managed volume
? docker run -it -name bbox1 –v /data busybox
? docker inspect -f {{.Mounts}} bbox1
? 查看bbox1容器的卷、卷标识符及挂载的主机目录
? Bind-mount Volume
? docker run -it -v HOSTDIR:VOLUMEDIR --name bbox2 busybox
? docker inspect -f {{.Mounts}} bbox2
docker volume ls 查看已存在的volume
docker volume inspect filename 查看卷的详细信息
两个容器共用一个存储卷,就可以共享数据
?多个容器的卷使用同一个主机目录,例如
? docker run –it --name c1 -v /docker/volumes/v1:/data busybox
? docker run –it --name c2 -v /docker/volumes/v1:/data busybox
?复制使用其它容器的卷,为docker run命令使用--volumes-from选项
? docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox
? docker run -it --name bbox2 --volumes-from bbox1 busybox
配置容器化应用
? MariaDB:
? 命令行选项:使程序运行特性和程序解耦
? 配置文件
? 容器化方式运行MariaDB
? 启动容器
? exec -it
? 配置容器化应用
? docker run
? 通过自定义要运行的命令,并向传递命令行参数;
? 自定义镜像,将修改好的配置文件直接焙进镜像。不同环境不同的镜像
? 环境变量,应用程序支持变量配置,容器启动时通过加载用户传入的变量值,实现同一个镜像,不同的运行环境。但传统意义上的应用大部分都不支持次方法
? docker run -e
? 存储卷:把配置文件在本地编辑好,启动时加载特定的volume
但这些配置方式都需要一个docker额外的平台,通过这个平台去管理docker,而不是直接通过docker
容器化时代静态已不是主流,动态才是,动态化是容器时代的一大特征。
容器和进程
? 容器:一个进程;
? 进程终止,必将导致容器终止;
? 传递终止信号:SIGTERM,SIGKILL
? 进程没终止:running
? 健康状态检测
? 通过重启自愈,镜像内部应该有自愈机制
配置中心:专门的键值存储系统,Redis、etcd
程序通过watch监测,当配置中心的配置文件发生变化时从配置中心加载配置,reload配置。此时就可以达到以一应百。
注册中心,配置中心
Docker file
Dockerfile:Dockerfile is nothing but the source code for building,制作docker镜像的指令、源码。
? docker build:根据docker file里的指令根据指定的某一个基础镜像来制作docker image
? Dokcerfile必须放在workdir目录下,build把workdir作为根,所以所有build用到的文件必须放在workdir下
? docker build必须基于一个基础镜像制作新的镜像,不可能完全制作一个新镜像
? 一个docker file中一条指令就一层镜像,所以镜像层次越少越好
? docker build在制作过程中会基于base image启动一个容器
? dockerfile所支持的命令和制作环境都是基于基础镜像的,不是基于宿主机的
? 指令全大写,易于区分参数和指令,第一个指令必须是FROM
? dockerignore file:指定要排除的文件
dockerfile instruction
FROM:指定docker build的basic image
Syntax
? FROM <repository>[:<tag>] 或
? FROM <resository>@<digest> -->digest:镜像的校验码,
? <reposotiry>:指定作为base image的名称;
? <tag>:base image的标签,为可选项,省略时默认为latest;
MAINTANIER:指定作者信息(以后会被替代,建议不要用)
? Syntax
? MAINTAINER <authtor‘s detail>
? <author‘s detail>可是任何文本信息,但约定俗成地使用作者名称及邮件地址
LABEL:指定作者信息
? Syntax: LABEL <key>=<value> <key>=<value> <key>=<value> ...
COPY:用于Docker主机复制文件至创建的新映像文件
? Syntax
? COPY <src> ... <dest> 或
? COPY ["<src>",... "<dest>"] ? <src>:要复制的源文件或目录,支持使用通配符
? <dest>:目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;
? 注意:在路径中有空白字符时,通常使用第二种格式
?文件复制准则
? <src>必须是build上下文中的路径,不能是其父目录中的文件
? 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
? 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
? 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径
ADD
?ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
? Syntax
? ADD <src> ... <dest> 或
? ADD ["<src>",... "<dest>"]
?操作准则
? 同COPY指令
? 如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
? 如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;
? 如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;
WORKDIR
?用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
? Syntax
? WORKDIR <dirpath>
? 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
? 另外,WORKDIR也可调用由ENV指定定义的变量
? 例
? WORKDIR /var/log
? WORKDIR $STATEPATH
VOLUME
?用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
? Syntax
? VOLUME <mountpoint> 或
? VOLUME ["<mountpoint>"]
?如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
EXPOSE
?用于为容器打开指定要监听的端口以实现与外部通信
? Syntax
? EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]
? <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
? EXPOSE指令可一次指定多个端口,例如
? EXPOSE 11211/udp 11211/tcp
docker run --name web1 -it --rm -P tinyweb:v0.1 创建容器的时候,需要通过-P选项来暴露EXPOSE指定的端口
ENV
?用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令如ENV、ADD、COPY等)所调用
?调用格式为$variable_name或${variable_name}
? Syntax
? ENV <key> <value> 或
? ENV <key>=<value> ...
? 第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量;
? 第二种格式可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线()进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行;
? 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
Dockerfile 中指定的变量只能在docker build中使用,docker run指定的变量在docker container中使用。
RUN
?用于指定docker build过程中运行的程序,其可以是任何命令
? Syntax
? RUN <command> 或
? RUN ["<executable>", "<param1>", "<param2>"]
? 第一种格式中,<command>通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器
时,此进程接收不到SIGTERM信号;
? 第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起
,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
? RUN ["/bin/sh", "-c", "<executable>", "<param1>"]
?注意:json数组中,要使用双引号
CMD
?类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
? RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时
? CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
? 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
? Syntax
? CMD <command> 或 作为shell的子命令运行
? CMD [“<executable>”, “<param1>”, “<param2>”] 或
? CMD ["<param1>","<param2>"]
?前两种语法格式的意义同RUN
?第三种则用于为ENTRYPOINT指令提供默认参数
ENTRYPOINT
?类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
?与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
? 不过,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
? Syntax
? ENTRYPOINT <command>
? ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
? docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
? Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
如果CMD和ENTRYPOINT同时存在,CMD作为ENTRYPOINT的参数运行。
在docker run时也可以通过docker -e来改变环境变量
USER
?用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID
?默认情况下,container的运行身份为root用户
? Syntax
? USER <UID>|<UserName>
? 需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败
HELTHCHECK
? 检测容器的健康状态
HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
HEALTHCHECK NONE (disable any healthcheck inherited from the base image)
[options]:
--interval=DURATION (default: 30s) 间隔时长
--timeout=DURATION (default: 30s) 超时时长
--start-period=DURATION (default: 0s) container启动之后多久开始监测
--retries=N (default: 3) 重试次数
退出码含意
0: success - the container is healthy and ready for use
1: unhealthy - the container is not working correctly
2: reserved - do not use this exit code
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
如果容器自己没有健康检测,则可以在docker run时通过-e 定义
SHELL
改变系统默认的shell程序,因为基础镜像可能是windows。
STOPSIGNAL
指定系统的终止信号,默认为9
ARG
在build镜像的时候,通过 --build-arg 来传递参数给ARG定义的变量,而不用事先在Dockerfile中定义好
Syntax:ARG<name>[=<default value>]
ONBUILD
在Dockerfile中定义一个指令,ONBULID后面必须跟一个正常的Dockerfile指令,我们自己build的镜像可能被别人作为FROM镜像。ONBUILD后面的指令在我们build时不执行,当别人用我们的镜像build时ONBUILD才会执行。
所以任何来路不明的镜像都不应该被运行。
以上是关于Dokcer入门及其Docker file的制作指令的主要内容,如果未能解决你的问题,请参考以下文章
云原生之Dokcer实战使用Docker部署openwrt软路由