docker的产生及应用

一、docker的产生和概述

  docker技术主要是为程序部署和运维而产生的,对部署来说它提供了一个能让程序正常运行的封装环境,它避免了不同环境配置导致的程序无法运行的尴尬,它的思想理念是镜像封装,达到一次封装多处运行的目的。其次对高并发、高可用程序来说,是实现服务集群的基石。Docker技术是在Linux容器技术的基础上发展而来,所以说docker实质上就是一项容器虚拟化技术。

  提到容器就不得不提到虚拟机,容器和虚拟机的本质是一样的,虚拟机虚拟的是一套带软件和硬件的完整解决方案,其缺点有占用资源、步骤冗余、启动慢等,而容器是在虚拟机之上对进程进行隔离,形成一个个独立的容器,这些容器只包含程序运行必须的软件环境,因此具有启动快、占用硬件资源少等特点,容器实质上可看作是一个基础镜像系统+应用程序的简版系统。

  docker技术包含三个部分,即仓库、镜像、容器,容器是运行程序的最小单元,它是镜像的实例;镜像是容器的模板,容器运行需要借助镜像来装载环境;仓库用于存储镜像文件,通常分为中央仓库、私有仓库、本地仓库; 三者之间的关系类似于java面向对象中的包、类、对象的关系。

  目前最大仓库是Docker Hub,国内公开仓库有阿里云仓库、网易云等。

二、docker运行原理

  docker是一个client-server结构的系统,使用远程API来管理和创建Docker容器,docker守护进程运行在主机上,从客户端通过socket连接守护进程,守护进程会从客户端接收命令并管理运行在主机上的容器。

  docker客户端通过socket连接docker守护进程,默认Docker守护进程的客户端接收端口为2375,且为关闭状态,如果需要远程客户端连接,则需要开启该功能,linux通常修改/usr/lib/systemd/system/docker.service文件,为ExecStart加入 -H参数来实现,例如:

     ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock  

  docker的详细命令请参考帮助命令(docker  --help)输出的内容( 命令语法格式: docker [OPTIONS] COMMAND  [ARG...] ),OPTIONS为可选项,参考options选项说明,COMMAND为命令,包括管理命令和普通命令,参考managerCommands和commands说明, ARG为参数(容器ID、镜像名等表示命令要操作的对象)。参考常见命令有docker version、docker info、docker images、docker ps、docker rm 、docker search、docker run、docker logs、docker inspect。

  docker的镜像实际上是由一层一层的文件系统构成,这种层级的文件系统称为UnionFS。UnionFS文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,UnionFS文件系统是Dokcer镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的镜像。一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统加载起来,这样最终的文件系统会包含所有的底层文件和目录。

  UnionFS主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的linux/unix系统是一样的,包含boot加载器内核。当boot加载完之后整个内核就都在内存中了,此时内存的使用权已经由bootfs交给内核了,此时系统也会卸载bootfs。对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就行,因为底层直接用host和kernel,自己只需要提供rootfs就行。由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。

  在下载镜像的过程中我们可以看到docker的镜像好像是在一层一层的下载,这些层其实都是文件系统,使用分层思想主要是为了实现文件系统的共享,比如多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也需要加载一份base镜像,就可以为所有上层文件系统提供服务了。而且镜像的每一层都可以被共享。

  Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层,其构建过程 如下:

  当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下都叫“镜像层”,可写层可以改动,镜像层则为只读的,其容器的结构如下图:

   Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了,为此我们使用数据卷来持久化数据。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷,无主的数据卷可能会占据很多空间,所以要及时删除。使用数据卷可以实现多个容器和宿主机之间数据共享,数据卷类似于局域网的共享文件或文件,特点如下:

  1. 数据卷存在于宿主机的文件系统中,独立于容器,和容器的生命周期是分离的。
  2. 数据卷可以是目录也可以是文件,容器可以利用数据卷与宿主机进行数据共享。
  3. 容器启动初始化时,如果容器使用的镜像包含了数据,这些数据会拷贝到数据卷中。
  4. 容器对数据卷的修改是实时进行的。
  5. 数据卷的变化不会影响镜像的更新。数据卷是独立于联合文件系统,镜像是基于联合文件系统。镜像与数据卷之间不会相互影响。

  镜像本身是不可描述的,Docker提供了镜像文件Dockerfile机制,Dockerfile是一个文本文件,内容包含了一条条构建镜像所需的指令和说明, 它可以用来构建镜像,我们还可以通过它了解镜像的信息和功能。因此镜像的产生有仓库拉取、commit、dockerfile构建等几种方式,如图所示:

三、docker的安装和使用

  1、docker安装参考https://www.w3cschool.cn/docker/,还可以参考docker官网,该教程包含了不同系统的安装方式,此处省略,国外下载镜像慢,推荐使用阿里云的镜像加速器下载镜像。镜像加速器的使用和配置方式请参考阿里云镜像加速器操作文档。

  2、下载和运行镜像:运行容器需要先从镜像仓库下载镜像到本地后运行,其下载命令为docker pull imagesname:tagname,运行命令为docker run imagesName:tagname,运行命令会先从本地查找,如果镜像不存在,则会从仓库下载。

  3、常用的docker命令和参数说明:

Docker环境信息 — docker [info|version]
容器生命周期管理 — docker [create|exec|run|start|stop|restart|kill|rm|pause|unpause]
容器操作运维 — docker [ps|inspect|top|attach|wait|export|port|rename|stat]
容器rootfs命令 — docker [commit|cp|diff]
镜像仓库 — docker [login|pull|push|search]
本地镜像管理 — docker [build|images|rmi|tag|save|import|load]
容器资源管理 — docker [volume|network]
系统日志信息 — docker [events|history|logs]
管理命令:
  container   管理容器
  image       管理镜像
  network     管理网络

命令:
  attach      介入到一个正在运行的容器
  build       根据 Dockerfile 构建一个镜像
  commit      根据容器的更改创建一个新的镜像
  cp          在本地文件系统与容器中复制 文件/文件夹
  create      创建一个新容器
  exec        在容器中执行一条命令
  images      列出镜像
  kill        杀死一个或多个正在运行的容器   
  logs        取得容器的日志
  pause       暂停一个或多个容器的所有进程
  ps          列出所有容器
  pull        拉取一个镜像或仓库到 registry
  push        推送一个镜像或仓库到 registry
  rename      重命名一个容器
  restart     重新启动一个或多个容器
  rm          删除一个或多个容器
  rmi         删除一个或多个镜像
  run         在一个新的容器中执行一条命令
  search      在 Docker Hub 中搜索镜像
  start       启动一个或多个已经停止运行的容器
  stats       显示一个容器的实时资源占用
  stop        停止一个或多个正在运行的容器
  tag         为镜像创建一个新的标签
  top         显示一个容器内的所有进程
  unpause     恢复一个或多个容器内所有被暂停的进程 

docker run 命令常用参数:
    --name:为容器指定名称
    -it:启动一个交互型容器,此参数为我们和容器提供了一个交互shell
    -d:创建后台型容器
    -restart=always:容器退出后自动重启
    -restart=on-failure:x:容器退出时如果返回值是非0,就会尝试重启x次
    -p x:y :主机端口:容器端口
    -P:随机分配一个49000到49900的端口
    -v:创建数据卷
    -n :指定dns
    -h : 指定容器的hostname
    -e :设置环境变量
     -m :设置容器使用内存最大值
    --net: 指定容器的网络连接类型,支持 bridge/host/none/container
    --link=x: 添加链接到另一个容器x
    --expose=x: 开放端口x

docker ps 命令常用参数:
    -a:查看所有容器
    -l:只列出最近创建的
    -n=x:只列出最后创建的x个
    -q:只列出容器id

docker rm 命令常用参数:
    -f:强制删除运行中的容器
    docker rm `docker ps -aq`:删除所有容器

docker logs 命令常用参数:
    -f:实时查看日志
    --tail=x:查看最后x行
    -t:查看日志产生的时间

  4、数据卷的添加方式:

    a.使用docker命令的  -v 选项配置,格式为 “ docker run -it  -v  /宿主机绝对路径目录或文件 :/容器内目录或文件  镜像名”。

    b.使用dockerfile文件配置,在donckerfile文件中使用VOLUME命令指定数据卷。

  5、数据卷容器的使用:数据卷可以通过容器来实现继承,达到数据卷共享的目的,提供数据卷的容器称为数据卷容器(父容器),例如以下命令创建了1个父容器和2个子容器,这三个容器都共享同一个数据卷。

docker run -it --parentcentos  centos   //创建父容器
docker run -it --child1  --volumes-from  parentcentos  centos  //数据卷来自父容器
docker run -it --child2  --volumes-from  parentcentos  centos  //数据卷来自父容器

//经过继承,三者都使用同一个数据卷,达到容器之间共享数据卷的目的

  6、dockerfile文件的使用:要使用dockerfile构建镜像首先是编写dockerfile文件,然后调用" docker build  -f dockefikename  -t  imagesname:tag "命令即可构建。其dockerfile文件内容格式要求和说明:

    a.每条指令必须大写且必须跟参数;

    b.指令按顺序执行;

    c.#表示注释;

    d.每条指令都会创建一个新的镜像层,并对镜像进行提交,当所有命令执行完成后形成一个新的镜像;

  其内容描述模板参考如下:

# Base images 基础镜像
FROM centos

#MAINTAINER 作者姓名和邮箱
MAINTAINER zqf<92973322@qq.com> 

#ENV 设置环境变量,可通过 $变量名 引用
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压,这与COPY命令差不多,区别是COPY不会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/  
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 执行以下命令 
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd,登录时切换到的目录
WORKDIR /usr/local/nginx-1.8.0 

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install

RUN echo "daemon off;" >> /etc/nginx.conf

#挂在数据卷
VOLUME /data : /usr

#镜像被子镜像继承后构建时,运行的命令
ONBUILD  ["nginx"]
#
EXPOSE 映射端口 EXPOSE 80 #CMD 容器启动时要运行的命令,如果有多个CMD则前面的会被覆盖,也会被dockr run 后面的脚本参数替换 CMD ["nginx"] #容器启动时要运行的命令,有多个时会追加执行命令,而不会CMD那样被覆盖 ENTRYPOINT ["nginx"]

 四、镜像发布到仓库

  通常镜像打包后需要送到云镜像仓库,首先需要在阿里云、腾讯云等平台开通镜像仓库功能,或者自己搭建仓库,再按照平台操作文档使用账号密码登录到仓库,后使用“docker push   仓库地址/imagesname:[tag]”命令执行推送。

五、Docker容器通信

  Docker容器之间的通信是通过网络来进行的,默认情况下Docker安装后会默认创建三种网络bridge(桥接模式)、host(主机模式)、none(无网络模式),此外还有container(容器共享模式)。

  • bridge模式:该模式是docker默认使用的网络模式。Docker在启动时会在宿主机上创建一个名为docker0的网桥,该网桥连接物理网卡,主机和容器之间可以通过该网桥通信。网桥是容器的默认网关,容器启动时会根据往前的IP段分配一个IP地址。

 

  • host模式:docker直接使用容器宿主机的网络,在容器上看到的网卡IP就是宿主机上的IP,不同的容器绑定不同的主机端口。

 

  • container模式:多个容器使用共同的网络,这些共用的容器的IP是同一个,该IP并不是宿主机的IP,而是通过Docker网桥docker0分配的。

 

  • none模式:Docker容器不进行任何网络配置,这个Docker容器没有网卡、IP、路由等信息,需要我们自行配置。

  了解以上4种Docker常用的网络模式,有利于我们在部署docker容器时根据网络安全隔离的防护要求去选择合适的网络模式,我们可通过"docker network 命令"来管理网络:

docker network connect 将容器连接到网络
docker network create 创建一个网络
docker network disconnect 断开容器与网络的连接
docker network inspect 显示一个或多个网络的详细信息
docker network ls 显示网络列表
docker network prune 删除所有未使用的网络
docker network rm 删除一个或者多个网络

六、Docker配置文件

  daemon.json是docker容器提供的配置文件,通过该文件可以自定义一些默认行为,几乎涵盖了所有docker命令行启动时可以配置的参数,该文件默认位于主机的/etc/docker目录中,通常安装时不会生成该文件,需要配置时手动创建。常用文件配置说明如下:

 1 {
 2 “api-cors-header”:"", # ——————在引擎API中设置CORS标头
 3 “authorization-plugins”:[], # ——————要加载的授权插件
 4 “bridge”:"", ————将容器附加到网桥
 5 “cgroup-parent”:"", # ——————为所有容器设置父cgroup
 6 “cluster-store”:"", # ——————分布式存储后端的URL
 7 “cluster-store-opts”:{}, # ————————设置集群存储选项(默认map [])
 8 “cluster-advertise”:"", # ————————要通告的地址或接口名称
 9 “debug”: true, # ————————启用调试模式,启用后,可以看到很多的启动信息。默认false
10 “default-gateway”:"", # ——————容器默认网关IPv4地址
11 “default-gateway-v6”:"", # ——————容器默认网关IPv6地址
12 “default-runtime”:“runc”, # ————————容器的默认OCI运行时(默认为“ runc”)
13 “default-ulimits”:{}, # ——————容器的默认ulimit(默认[])
14 “dns”: [“192.168.1.1”], # ——————设定容器DNS的地址,在容器的 /etc/resolv.conf文件中可查看。
15 “dns-opts”: [], # ————————容器 /etc/resolv.conf 文件,其他设置
16 “dns-search”: [], # ————————设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的 主机时,DNS不仅搜索host,还会搜
17 索host.example.com 。 注意:如果不设置, Docker 会默认用主机上的 /etc/resolv.conf 来配置容器。
18 “exec-opts”: [], # ————————运行时执行选项
19 “exec-root”:"", # ————————执行状态文件的根目录(默认为’/var/run/docker‘)
20 “fixed-cidr”:"", # ————————固定IP的IPv4子网
21 “fixed-cidr-v6”:"", # ————————固定IP的IPv6子网
22 “data-root”:"/var/lib/docker", ————-Docker运行时使用的根路径,默认/var/lib/docker
23 “group”: “”, # ——————UNIX套接字的组(默认为“docker”)
24 “hosts”: [], # ——————设置容器hosts
25 “icc”: false, # ——————启用容器间通信(默认为true)
26 “ip”:“0.0.0.0”, # ————————绑定容器端口时的默认IP(默认0.0.0.0)
27 “iptables”: false, # ———————启用iptables规则添加(默认为true)
28 “ipv6”: false, # ——————启用IPv6网络
29 “ip-forward”: false, # ————————默认true, 启用 net.ipv4.ip_forward ,进入容器后使用 sysctl -a | grepnet.ipv4.ip_forward 查看
30 “ip-masq”:false, # ——————启用IP伪装(默认为true)
31 “labels”:[“nodeName=node-121”], # ————————docker主机的标签,很实用的功能,例如定义:–label nodeName=host-121
32 “live-restore”: true, # ——————在容器仍在运行时启用docker的实时还原
33 “log-driver”:"", # ——————容器日志的默认驱动程序(默认为“ json-file”)
34 “log-level”:"", # ——————设置日志记录级别(“调试”,“信息”,“警告”,“错误”,“致命”)(默认为“信息”)
35 “max-concurrent-downloads”:3, # ——————设置每个请求的最大并发下载量(默认为3)
36 “max-concurrent-uploads”:5, # ——————设置每次推送的最大同时上传数(默认为5)
37 “mtu”: 0, # ——————设置容器网络MTU
38 “oom-score-adjust”:-500, # ——————设置守护程序的oom_score_adj(默认值为-500)
39 “pidfile”: “”, # ——————Docker守护进程的PID文件
40 “raw-logs”: false, # ——————全时间戳机制
41 “selinux-enabled”: false, # ——————默认 false,启用selinux支持
42 “storage-driver”:"", # ——————要使用的存储驱动程序
43 “swarm-default-advertise-addr”:"", # ——————设置默认地址或群集广告地址的接口
44 “tls”: true, # ————————默认 false, 启动TLS认证开关
45 “tlscacert”: “”, # ——————默认 ~/.docker/ca.pem,通过CA认证过的的certificate文件路径
46 “tlscert”: “”, # ————————默认 ~/.docker/cert.pem ,TLS的certificate文件路径
47 “tlskey”: “”, # ————————默认~/.docker/key.pem,TLS的key文件路径
48 “tlsverify”: true, # ————————默认false,使用TLS并做后台进程与客户端通讯的验证
49 “userland-proxy”:false, # ——————使用userland代理进行环回流量(默认为true)
50 “userns-remap”:"", # ————————用户名称空间的用户/组设置
51 “bip”:“192.168.88.0/22”, # ——————————指定网桥IP
52 “registry-mirrors”: [“https://192.498.89.232:89”], # ————————设置镜像加速
53 “insecure-registries”: [“120.123.122.123:12312”], # ———————设置私有仓库地址可以设为http
54 “storage-opts”: [
55 “overlay2.override_kernel_check=true”,
56 “overlay2.size=15G”
57 ], # ————————存储驱动程序选项
58 “log-opts”: {
59 “max-file”: “3”,
60 “max-size”: “10m”,
61 }, # ————————容器默认日志驱动程序选项
62 “iptables”: false # ————————启用iptables规则添加(默认为true)
63 }
daemon.json

七、Docker日志功能

  Docker日志包容器日志和守护进程日志两类。容器日志是Docker容器中运行的应用生成的,stdout表示应用正常的控制台输出日志,stderr表示应用错误的控制台输出日志,这些日志可以通过logging driver日志驱动程序进行不同的保存,以便docker logs命令进行访问,通过该日志可以追踪我们自身部署的应用情况;守护进程日志是Docker引擎本身生成的日志,用于记录容器的启动、停止等活动,同时也包含守护进程运行状态和错误信息。

  • 容器日志:前面提到容器日志是容器内应用输出的,Docker使用日志驱动程序来保存日志,默认使用json-file驱动模式,日志文件存放在/var/lib/docker/containers/$CONTAINER_ID/$CONTAINER_ID-json.log中,一般情况下需要限制文件的最大大小,否则文件会无限增加,最终占满磁盘空间。以下是不同的驱动模式说明。
DriverDescription
none 丢弃容器输出,不进行任何记录
local 日志以自定义格式存储
json-file 日志存储格式为json, 默认的logdriver驱动
syslog 日志写入到指定的syslog地址
journald 日志写入到指定jounald
gelf 以gelf格式发送日志
fluentd 日志发送到指定的fluentd服务
awslogs 日志发送到指定的Amazon CloudWatch Logs
splunk 日志发送到指定的splunk服务
etwlogs 日志发送到Event Tracing for Windows, 仅支持windows平台
gcplogs 日志发送到Google Cloud日志系统
logentries 日志发送到Rapid7 Logentries

  •  守护进程日志:这些日志都是保存在宿主机器中的,该日志一般交给Upstart或者systemd管理,前者通过cat /var/log/upstart/docker.log查看,后者通过journalctl -u docker.service查看。

八、Docker架构的缺陷和安全问题

  1、Docker自身漏洞:Docker本身可能存在未知漏洞,黑客可以通过漏洞执行代码、权限提升、 信息泄露、权限绕过等方式发起攻击,因此应该及时的更新迭代版本。

  2、镜像安全:Docker提供了免费的镜像仓库,存在大量的用户上传的镜像,供其他用户下载使用,这会导致大量包含恶意代码的镜像,或者镜像包含软件漏洞,需要我们自行识别。

  3、Docker局域网攻击:Docker容器之间通过Docker局域网通信,我们需要配置合理的局域网规则来避免ARP 欺骗、嗅探、广播风暴等攻击。

  4、宿主机越权攻击:Docker与宿主机共用一个操作系统内核,如果宿主内核存在可以越权或者提权漏洞,尽管Docker使用普通用户执行,也会利用漏洞攻击宿主机。

  5、Docker共享root用户权限:Docker容器与宿主机处于共享同一个内核操作系统的状态,因此Docker容器的root用户将获得37项Capabilities能力,完全拥有内核的管理权限(有人验证说宿主机的root用户和docker的root用是同一个?好可怕),通常容器技术也会针对这种情况将容器中的进程能访问的资源封锁在容器中,但是也不排除进程有访问宿主资源的情况,这会导致宿主机容易被容器内的进程进行穿透攻击。因此强烈建议不使用root用户运行Docker容器!!!当然Docker提供了用户命名空间namespace隔离技术的概念,该机制用于隔离用户权限,进行用户权限管理。

  6、Docker客户端与Docker守护进程的通信安全问题:客户端与守护进程通过Socket访问,端口默认2375,为关闭状态,开启该端口后如果不加限制,任何人都可以向该接口提交命令,这是极不安全的,推荐使用TLS加密认证。

  7、数据安全:Docker容器生成的数据如果不使用持久卷,则删除容器后数据酒丢失了,因此对必须的数据要进行数据卷挂载。

九、Docker容器使用的安全建议

  1、及时更新版本。

  2、不下载来历不明的,非官方的镜像。

  3、使用iptables配置局域网的包过滤规则。

  4、Docker容器运行时默认使用root用户,需使用参数指定Docker容器运行用户。

  5、使用用户命名空间namespace隔离技术来管理容器用户权限。

  6、Docker客户端与守护进程的通信使用IP白名单、TLS加密认证等方式来限制非法客户端。

  7、容器生成的数据需要使用数据卷持久化。

十、Docker相关文件夹解读

  1./var/lib/docker/containers/

  在linux中,/var/lib/docker/containers/是容器数据的存放根目录,在Docker中每个容器都被认为是一个独立的实体,对应一个子目录,子目录通常由容器ID组成。子目录包含如下主要文件:

  • config.v2.json:包含容器的配置信息,如容器的名称、镜像、挂载卷、环境变量等。
  1 {
  2     "StreamConfig": {},
  3     "State": {
  4         "Running": true,
  5         "Paused": false,
  6         "Restarting": false,
  7         "OOMKilled": false,
  8         "RemovalInProgress": false,
  9         "Dead": false,
 10         "Pid": 6851,
 11         "ExitCode": 0,
 12         "Error": "",
 13         "StartedAt": "2023-09-11T01:53:10.902440566Z",
 14         "FinishedAt": "2023-09-11T01:53:10.45822398Z",
 15         "Health": null
 16     },
 17     "ID": "094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844",
 18     "Created": "2023-06-28T03:44:31.948364743Z",
 19     "Managed": false,
 20     "Path": "/docker-entrypoint.sh",
 21     "Args": ["nginx", "-g", "daemon off;"],
 22     "Config": {
 23         "Hostname": "b8adc284eed7",
 24         "Domainname": "",
 25         "User": "",
 26         "AttachStdin": false,
 27         "AttachStdout": false,
 28         "AttachStderr": false,
 29         "ExposedPorts": {
 30             "80/tcp": {},
 31             "8080/tcp": {},
 32             "8081/tcp": {},
 33             "8082/tcp": {}
 34         },
 35         "Tty": false,
 36         "OpenStdin": false,
 37         "StdinOnce": false,
 38         "Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.21.5", "NJS_VERSION=0.7.1", "PKG_RELEASE=1~bullseye"],
 39         "Cmd": ["nginx", "-g", "daemon off;"],
 40         "Image": "nginx:latest",
 41         "Volumes": {
 42             "/etc/nginx/cert.key": {},
 43             "/etc/nginx/cert.pem": {},
 44             "/etc/nginx/conf.d": {},
 45             "/etc/nginx/nginx.conf": {},
 46             "/usr/share/nginx/html": {},
 47             "/var/log/nginx": {}
 48         },
 49         "WorkingDir": "",
 50         "Entrypoint": ["/docker-entrypoint.sh"],
 51         "OnBuild": null,
 52         "Labels": {
 53             "maintainer": "NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e"
 54         },
 55         "StopSignal": "SIGQUIT"
 56     },
 57     "Image": "sha256:eb4a57159180767450cb8426e6367f11b999653d8f185b5e3b78a9ca30c2c31d",
 58     "NetworkSettings": {
 59         "Bridge": "",
 60         "SandboxID": "9971b80389fee7cb1bb34bdc32079bb1e3b373de508626faf97fe4d9f4b79f05",
 61         "HairpinMode": false,
 62         "LinkLocalIPv6Address": "",
 63         "LinkLocalIPv6PrefixLen": 0,
 64         "Networks": {
 65             "bridge": {
 66                 "IPAMConfig": {},
 67                 "Links": null,
 68                 "Aliases": null,
 69                 "NetworkID": "aaf2e345dbe9dce9782c93080c2a997bf00807c46a1fedd08cb89ca5eb8354b8",
 70                 "EndpointID": "ade2943647645ed1d499a5df8e35f58dc8f8d182edd38de0cd96ed8550acf6bf",
 71                 "Gateway": "172.17.0.1",
 72                 "IPAddress": "172.17.0.4",
 73                 "IPPrefixLen": 16,
 74                 "IPv6Gateway": "",
 75                 "GlobalIPv6Address": "",
 76                 "GlobalIPv6PrefixLen": 0,
 77                 "MacAddress": "02:42:ac:11:00:04",
 78                 "DriverOpts": null,
 79                 "IPAMOperational": false
 80             }
 81         },
 82         "Service": null,
 83         "Ports": {
 84             "80/tcp": [{
 85                 "HostIp": "0.0.0.0",
 86                 "HostPort": "80"
 87             }, {
 88                 "HostIp": "::",
 89                 "HostPort": "80"
 90             }],
 91             "8080/tcp": [{
 92                 "HostIp": "0.0.0.0",
 93                 "HostPort": "8080"
 94             }, {
 95                 "HostIp": "::",
 96                 "HostPort": "8080"
 97             }],
 98             "8081/tcp": [{
 99                 "HostIp": "0.0.0.0",
100                 "HostPort": "8081"
101             }, {
102                 "HostIp": "::",
103                 "HostPort": "8081"
104             }],
105             "8082/tcp": [{
106                 "HostIp": "0.0.0.0",
107                 "HostPort": "8082"
108             }, {
109                 "HostIp": "::",
110                 "HostPort": "8082"
111             }]
112         },
113         "SandboxKey": "/var/run/docker/netns/9971b80389fe",
114         "SecondaryIPAddresses": null,
115         "SecondaryIPv6Addresses": null,
116         "IsAnonymousEndpoint": false,
117         "HasSwarmEndpoint": false
118     },
119     "LogPath": "/var/lib/docker/containers/094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844/094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844-json.log",
120     "Name": "/nginx",
121     "Driver": "overlay2",
122     "OS": "linux",
123     "MountLabel": "",
124     "ProcessLabel": "",
125     "RestartCount": 0,
126     "HasBeenStartedBefore": true,
127     "HasBeenManuallyStopped": false,
128     "MountPoints": {
129         "/etc/nginx/cert.key": {
130             "Source": "/docker_filePath/nginx/conf/cert.key",
131             "Destination": "/etc/nginx/cert.key",
132             "RW": true,
133             "Name": "",
134             "Driver": "",
135             "Type": "bind",
136             "Propagation": "rprivate",
137             "Spec": {
138                 "Type": "bind",
139                 "Source": "/docker_filePath/nginx/conf/cert.key",
140                 "Target": "/etc/nginx/cert.key"
141             },
142             "SkipMountpointCreation": false
143         },
144         "/etc/nginx/cert.pem": {
145             "Source": "/docker_filePath/nginx/conf/cert.pem",
146             "Destination": "/etc/nginx/cert.pem",
147             "RW": true,
148             "Name": "",
149             "Driver": "",
150             "Type": "bind",
151             "Propagation": "rprivate",
152             "Spec": {
153                 "Type": "bind",
154                 "Source": "/docker_filePath/nginx/conf/cert.pem",
155                 "Target": "/etc/nginx/cert.pem"
156             },
157             "SkipMountpointCreation": false
158         },
159         "/etc/nginx/conf.d": {
160             "Source": "/docker_filePath/nginx/conf.d",
161             "Destination": "/etc/nginx/conf.d",
162             "RW": true,
163             "Name": "",
164             "Driver": "",
165             "Type": "bind",
166             "Propagation": "rprivate",
167             "Spec": {
168                 "Type": "bind",
169                 "Source": "/docker_filePath/nginx/conf.d",
170                 "Target": "/etc/nginx/conf.d"
171             },
172             "SkipMountpointCreation": false
173         },
174         "/etc/nginx/nginx.conf": {
175             "Source": "/docker_filePath/nginx/conf/nginx.conf",
176             "Destination": "/etc/nginx/nginx.conf",
177             "RW": true,
178             "Name": "",
179             "Driver": "",
180             "Type": "bind",
181             "Propagation": "rprivate",
182             "Spec": {
183                 "Type": "bind",
184                 "Source": "/docker_filePath/nginx/conf/nginx.conf",
185                 "Target": "/etc/nginx/nginx.conf"
186             },
187             "SkipMountpointCreation": false
188         },
189         "/usr/share/nginx/html": {
190             "Source": "/docker_filePath/nginx/html",
191             "Destination": "/usr/share/nginx/html",
192             "RW": true,
193             "Name": "",
194             "Driver": "",
195             "Type": "bind",
196             "Propagation": "rprivate",
197             "Spec": {
198                 "Type": "bind",
199                 "Source": "/docker_filePath/nginx/html",
200                 "Target": "/usr/share/nginx/html"
201             },
202             "SkipMountpointCreation": false
203         },
204         "/var/log/nginx": {
205             "Source": "/docker_filePath/nginx/logs",
206             "Destination": "/var/log/nginx",
207             "RW": true,
208             "Name": "",
209             "Driver": "",
210             "Type": "bind",
211             "Propagation": "rprivate",
212             "Spec": {
213                 "Type": "bind",
214                 "Source": "/docker_filePath/nginx/logs",
215                 "Target": "/var/log/nginx"
216             },
217             "SkipMountpointCreation": false
218         }
219     },
220     "SecretReferences": null,
221     "ConfigReferences": null,
222     "AppArmorProfile": "",
223     "HostnamePath": "/var/lib/docker/containers/094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844/hostname",
224     "HostsPath": "/var/lib/docker/containers/094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844/hosts",
225     "ShmPath": "",
226     "ResolvConfPath": "/var/lib/docker/containers/094d2a1bdb547aa329dd4d810eed74e9576718b349b028d7574cd60c36d8f844/resolv.conf",
227     "SeccompProfile": "",
228     "NoNewPrivileges": false,
229     "LocalLogCacheMeta": {
230         "HaveNotifyEnabled": false
231     }
232 }
config.v2.json
  • hostname:包含容器的主机名。
  • resolv.conf:包含容器的 DNS 配置信息。
  • checkpoints:用于存储容器的检查点(Checkpoint)文件。
  • logs:用于存储容器的日志文件。
  • mounts:包含容器的挂载卷信息。
  • state:包含容器的状态信息,如容器的运行状态、进程信息等。
  • **-json.log:容器日志文件。

  2./var/lib/docker/image/

  在linux中,/var/lib/docker/image/目录用于存放镜像的元数据,该目录可能包含如下子目录,但是不同的docker版本使用的存储驱动不一样,一般只会有如下文件夹中的一个。/var/lib/docker/image目录是一个软链接,指向存储镜像文件的实际目录。

  • aufs:在旧版本的 Docker 中使用 AUFS 存储驱动,镜像的文件系统层会以 AUFS 格式存储在该目录中。

  • overlay2:在较新版本的 Docker 中使用 Overlay2 存储驱动,镜像的文件系统层会以 Overlay2 格式存储在该目录中。

  • overlay:在一些较旧的 Docker 版本中使用 Overlay 存储驱动,镜像的文件系统层会以 Overlay 格式存储在该目录中。

  • image.db: SQLite 数据库文件,用于存储 Docker 镜像的元数据信息,例如镜像的名称、标签、大小、创建时间等。

  • **/repositories.json:该文件存储的是本地所有的镜像列表信息,包括仓库、标签等信息。
 1 {
 2     "Repositories": {
 3         "ccr.ccs.tencentyun.com/zddcs/xx-admin": {
 4             "ccr.ccs.tencentyun.com/zddcs/xx-admin:1.0.0_dev": "sha256:682fbbd91a64e2cb91d317c5561b9fb3e2b9790505fa024eca78213f2bcaf5b5"
 5         },
 6         "ccr.ccs.tencentyun.com/zddcs/xx-pc": {
 7             "ccr.ccs.tencentyun.com/zddcs/xx-pc:1.0.0": "sha256:31576499321a97f5a2cfd708e9958e9ca5844d17f3a8cd7d6be1eacb526c5a79"
 8         },
 9         "ccr.ccs.tencentyun.com/zddcs/xx-admin": {
10             "ccr.ccs.tencentyun.com/zddcs/xx-admin:1.0.0.d_test": "sha256:e00ce01773771cc6b18a812991adef51316a66f791c6872788dcefb39cbc4e36",
11             "ccr.ccs.tencentyun.com/zddcs/xx-admin:1.0.0_test": "sha256:8937a735118a655bc430385229250adfa34483729a7c6ffa7543a28f37635069",
12         },
13         "ccr.ccs.tencentyun.com/zddcs/xx-pc_v2": {
14             "ccr.ccs.tencentyun.com/zddcs/xx-pc_v2:1.0.0-test": "sha256:abad5478361de7ff0ac8013502953b6f898025041974decf85a2425be52dbbc0",
15             "ccr.ccs.tencentyun.com/zddcs/xx-pc_v2@sha256:c1e74f2b84430ab59d89ed995618c94dba099ab52b76b5b0a715661363d459cf": "sha256:abad5478361de7ff0ac8013502953b6f898025041974decf85a2425be52dbbc0"
16         },
17         "mysql": {
18             "mysql:latest": "sha256:3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b",
19             "mysql@sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709": "sha256:3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b"
20         },
21         "nginx": {
22             "nginx:latest": "sha256:eb4a57159180767450cb8426e6367f11b999653d8f185b5e3b78a9ca30c2c31d",
23             "nginx@sha256:593dac25b7733ffb7afe1a72649a43e574778bf025ad60514ef40f6b5d606247": "sha256:eb4a57159180767450cb8426e6367f11b999653d8f185b5e3b78a9ca30c2c31d"
24         },
25         "openjdk": {
26             "openjdk:8-jre": "sha256:0c14a0e20aa3a19448f6227265c6642571112e9cd9a69b5e7a323df46d1aa835",
27             "openjdk@sha256:667a15e7bc533a90fb39ddb7e5bed63162ac3c13a97e6c698bf4f139f51b7d33": "sha256:0c14a0e20aa3a19448f6227265c6642571112e9cd9a69b5e7a323df46d1aa835"
28         },
29         "portainer/portainer": {
30             "portainer/portainer:latest": "sha256:580c0e4e98b06d258754cf28c55f21a6fa0dc386e6fe0bf67e453c3642de9b8b",
31             "portainer/portainer@sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f": "sha256:580c0e4e98b06d258754cf28c55f21a6fa0dc386e6fe0bf67e453c3642de9b8b"
32         },
33         "redis": {
34             "redis:latest": "sha256:7614ae9453d1d87e740a2056257a6de7135c84037c367e1fffa92ae922784631",
35             "redis@sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339": "sha256:7614ae9453d1d87e740a2056257a6de7135c84037c367e1fffa92ae922784631"
36         }
37     }
38 }
repositories.json

  3./var/lib/docker/volumes/

  在linux中,/var/lib/docker/volumes/目录用于存放容器数据卷,每个容器的数据卷对应一个子目录,子目录的名称是由一个唯一的 ID 组成,里面包含了该容器需要使用的应用数据信息。数据卷是Docker用于持久化存储容器数据的机制,可以在容器之间共享和重用数据。但是,并不是每个容器都需要使用数据卷,只有当容器需要持久化存储数据或者需要在多个容器之间共享数据时,才会创建数据卷。

  4./var/lib/docker/network/

  在linux中,/var/lib/docker/network/目录用于存放Docker网络配置信息,该目录包含了 Docker 网络驱动所使用的配置文件、网络插件、状态信息。

  5./var/lib/docker/overlay2/

  在linux中,/var/lib/docker/overlay2/目录用于存储镜像的文件系统层。

  6./var/lib/docker/plugins/

  在linux中,/var/lib/docker/plugins/目录用于存储镜像的文件系统层。

十一、疑问解答

  1.容器的仓库怎么进行自定义配置?

  答:Docker容器的仓库配置可以在Docker的配置文件或者在创建容器时通过命令行参数--registry-mirror进行配置。Docker的配置文件通常位于/etc/docker/daemon.json,如果该文件不存在,可以创建一个。在配置文件中可以添加仓库的地址,例如:

{
  "insecure-registries": ["myrepo.example.com"],
  "registry-mirrors": ["https://<your-mirror-domain>"],
  "registries": ["<your-registry-domain>"],
  ...
}

  2.docker日志文件如何清理?

  答:Docker提供了一些命令用于容器日志。比如清空所有容器的日志文件,可以运行docker container prune --filter "until=24h"命令,这个命令会删除所有已停止容器的日志,最后使用时间超过24小时的日志保留,可以根据需要更改24h参数来适应需求。如果要为单个容器清理日志,可以运行docker logs <container-id> > /dev/null命令,这个命令会在容器中检索所有的日志,然后输出到系统的/dev/null设备中,相当于清空了日志文件。还可以使用手动方式进入Docker日志文件夹(/var/lib/docker/containers/),执行find.-name"*.log"-typef-delete命令清除所有日志文件。

  3.如何备份Docker容器的配置信息?

  答:停止容器后使用docker export命令将容器导出为一个tar文件保存到安全位置,下次使用时可以使用docker import命令将tar文件导入到Docker中,从而快速恢复容器的配置信息。docker可以容器和镜像都打成tar包进行传输,例如使用docker save 命令和docker load命令可以打包镜像和加载镜像。

  4.docker export/import 和docker save/load的区别?

  答:docker export命令用于导出容器文件系统,docker save命令用于导出整个镜像及其元数据和配置信息。

  5.docker容器的状态有哪几种?

  答:created(已创建)\restarting(重启中)\running(运行中)\removing(迁移中)\paused(暂停中)\exited(已退出)\dead(已死亡)。容器应用的BUG\错误配置\资源不足会导致运行的容器无限重启。

  6.在使用docker容器时,通常我们需要使用-p进行端口映射,怎么知道容器内应用的端口是多少?

  答:容器内的应用端口是在构建镜像时就指定的,相同镜像生成的容器其内部应用端口是相同的。在dockerfile中可以使用EXPOSE指令来声明容器应用需要监听的端口。

十二、常用的镜像文件Dockerfile

  • VUE项目镜像
1 FROM docker.io/nginx
2 
3 LABEL maintainer="xxx"
4 
5 RUN rm /etc/nginx/conf.d/default.conf
6 
7 ADD default.conf /etc/nginx/conf.d/
8 
9 COPY dist/  /usr/share/nginx/html/
VUE前端镜像
  • Springboot项目镜像
 1 FROM openjdk:8-jre
 2 MAINTAINER xxx
 3 
 4 RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
 5     && echo "Asia/Shanghai" > /etc/timezone
 6 
 7 ARG JAR_FILE
 8 COPY ${JAR_FILE} /app.jar
 9 EXPOSE 8080
10 ENTRYPOINT ["java", "-jar", "/app.jar"]
SpringBoot项目镜像

 

posted @ 2022-03-31 00:49  我若安好,便是晴天  阅读(149)  评论(0编辑  收藏  举报