乐趣区

关于docker:墙裂推荐看完全面掌握最详细的-Docker-学习笔记总结2021最新版

Docker 是什么?

Docker 是一个开源的容器引擎,能够轻松的为任何利用创立一个轻量级的、可移植的、自力更生的容器。开发者和系统管理员在笔记本上编译测试通过的容器能够批量地在生产环境中部署,包含 VMs(虚拟机)、bare metal、OpenStack 集群、云端、数据中心和其余的根底利用平台。容器是齐全应用沙箱机制,相互之间不会有任何接口。

为啥要用 Docker?

为啥要用 Docker? 这要从目前软件行业的痛点来讲起

  • 1、软件更新公布及部署低效,过程繁琐且须要人工染指
  • 2、环境一致性难以保障
  • 3、不同环境之间迁徙老本太高

有了 Docker 能够很大水平解决下面的问题。

首先,Docker 的应用简略至极,从开发的角度来看就是三步走:构建,运输,运行。其中关键步骤就是构建环节,即打包镜像文件。然而从测试和运维的角度来看,那就只有两步:复制,运行。有了这个镜像,那么想复制到哪运行都能够,齐全和平台无关了。同时 Docker 这种容器技术隔离出了独立的运行空间,不会和其余利用争用系统资源了以及还不须要思考利用之间相互影响,想想就开心。

其次,因为在构建镜像的时候就解决完了服务程序对于零碎的所有依赖,所以在你应用的时候,你能够疏忽掉本来程序的依赖以及开发语言。对测试和运维而言,更多专一于本人的业务内容上。

最初,Docker 于开发者而言提供了一种开发环境的治理方法,与测试人员而言保障了环境的同步,于运维人员提供了可移植的标准化部署流程。

Docker 无能啥?

  • 构建容易散发简略
  • 隔离利用解除依赖
  • 疾速部署测完就销

Docker 的利用场景在哪??

  1. 本地依赖(Local Dependency)

你须要在本地零碎疾速尝试 Magento,或者为一个我的项目应用 MySQL?还是心愿尝试大部分开源我的项目?那就应用 Docker 吧,它将帮你节俭大量工夫。Docker 能晋升开发者的开发效率,让咱们疾速搭建开发环境。

开发环境的机器通常内存比拟小,此前应用虚构的时候,常常须要为开发环境的机器加内存,而通过 Docker 能够轻易的让几十个服务在 Docker 中跑起来。

  1. 搭建环境(Build Environment)

如果你心愿构建源码,但发现没有筹备好适合的环境。

那么应用 Docker 是一个值得思考的计划。毕竟如果应用传统的办法一个一个地装置软件,一大堆软件装置下来的确非常费时间,应用容器技术省时省力,何乐而不为?它能让你将运行环境和配置放在代码中而后部署,同一个 Docker 的配置能够在不同的环境中应用,这样就升高了硬件要求和应用环境之间耦合度。这里有一个值得一看的例子:docker golang builder。

  1. 微服务(Microservices)

你在应用微服务吗?微服务架构将一个整体式的利用拆分成松耦合的单个服务。

那无妨考虑一下 Docker,你能够将每个服务打包为一个 docker 镜像并应用 docker-compose 来模仿生产环境(checkout docker networks)。最开始实际的时候可能会比拟费时费力,但久远地来看,最终将产生微小的生产力。

  1. 自动测试(Automated testing)

试想这样一个问题,如何编写自动化的集成测试用例,这些测试用例无需花很长时间来开始运行,使用者也可轻松治理。这里不是指在 Docker 中运行测试用例,而是将测试用例与镜像严密运行在一起。当你针对一个 docker 镜像编写测试用例时会有一个很大的劣势。上面简略介绍一下我的测试流程:运行两个 docker 镜像(app + db),在 MySQL 启动时加载数据,并在 app docker 上应用 API。可查看此脚本以获取疾速的示例。

  1. 部署过程(Deployment process)

你能够应用 docker 镜像进行自我部署。许多支流的主机提供商都反对托管 docker,如果你领有一个具备 shell 拜访权限的专用节点 /vm,那么事件将变得更容易。只须要设置好 docker,并在你想要的端口上运行你的镜像即可。

  1. 继续部署(Continuous Deployment)

都说 Docker 天生适宜继续集成 / 继续部署,在部署中应用 Docker,继续部署将变得非常简单,并会在进入新的镜像后从新开始。对于这个局部的自动化工作,当初曾经有许多计划以供选择,Kubernetes 就是一个耳熟能详的名字。Kubernetes 是容器集群管理系统,是一个开源的平台,能够实现容器集群的自动化部署、主动扩缩容、保护等性能。

  1. 多租户环境(Multi-tenancy)

Docker 有意思的一个应用场景是在多租户的利用中,它能够防止要害利用的重写。如果你将应用程序服务公开给多个租户(租户指一组用户,例如组织),应用单租户方案设计的应用程序如果用上了 sub-domain + docker 能够疾速取得提供多租户的服务。
对于这个场景的一个例子是为物联网的利用开发一个疾速、易用的多租户环境。这种多租户的根本代码非常复杂,很难解决,从新布局这样一个利用岂但耗费工夫,也节约金钱。应用 Docker,能够为每一个租户的应用层的多个实例创立隔离的环境,这不仅简略而且老本低廉,当然这所有得益于 Docker 环境的启动速度和其高效的 diff 命令。

  1. 来自一台机器的多个 APP(Multiple apps from one machine)

这与下面提到的微服务有些分割,但即便你没有应用微服务,只是提供服务,Docker 仍能够很好地治理单个机器上的所有服务。你应该应用文件夹挂载来为每个基于数据的 docker 镜像保留数据。

  1. 扩容 QPS(Scaling QPS)

Docker 通过创立另一个容器来帮忙你轻松地进行程度扩大。如果遇到微小的顶峰流量,Docker 能够帮忙你解决问题 —— 只需增加更多的机器并减少负载均衡器背地运行的容器数量。

想全面理解的敌人能够参考:太全了|万字详解 Docker 架构原理、性能及应用

Docker 与 Openstack 比照

Docker 生态概览

Docker 装置

root@centos7 ~]# yum install docker -y
[root@centos7 ~]# systemctl start docker

下载镜像文件

[root@centos7 ~]# docker pull centos:latest
Trying to pull repository docker.io/library/centos ... 
centos7: Pulling from docker.io/library/centos
93857f76ae30: Pull complete 
Digest: sha256:4eda692c08e0a065ae91d74e82fff4af3da307b4341ad61fa61771cc4659af60
[root@centos7 ~]# docker images
REPOSITORY        TAG      IMAGE ID     CREATED     SIZE
docker.io/centos  centos7  a8493f5f50ff 3 days ago  192.5 MB

删除镜像

[root@centos7 ~]# docker rmi a8493f5f50ff    ## 容器 ID

Docker 容器创立与治理

1)创立容器

办法一:

[root@centos7 ~]# docker run centos /bin/echo "nihao"  ## 创立容器
nihao
[root@centos7 ~]# docker ps -a   ## 查看所有容器
CONTAINER ID  IMAGE  COMMAND   CREATED    STATUS   PORTS    NAMES
3c113f9a4f1b centos "/bin/echo nihao" 43 seconds ago Exited (0) 41 seconds ago  boring_liskov

这里没有指定容器名称,主动命名,状态是主动退出

办法二:创立一个自定义名称的容器

[root@centos7 ~]# docker run --name mgg -t -i centos /bin/bash
                              名称  调配伪终端  -i 处于关上状态
[root@2db7f1389dbd /]# ps -ef
UID   PID  PPID  C STIME TTY  TIME CMD
root   1    0  0 22:46 ?   00:00:00 /bin/bash
root   13   1  0 22:49 ?  00:00:00 ps -ef
[root@centos7 ~]# docker ps
CONTAINER ID  IMAGE   COMMAND   CREATED   STATUS  PORTS    NAMES
2db7f1389dbd  centos  "/bin/bash"  4 minutes ago   Up 4 minutes   mgg

docker ps - a 是显示所有容器包含没有运行的(同 virsh list –all)

2)进入、退出、启动容器

[root@2db7f1389dbd /]# exit   ## 退出容器
exit
[root@centos7 ~]# docker start 2db7f1389dbd   ## 启动容器
2db7f1389dbd
[root@centos7 ~]# docker attach 2db7f1389dbd  ## 进入容器(必须是启动状态下)[root@2db7f1389dbd /]# hostname
2db7f1389dbd

这种进入形式,退出后容器就进入 Down 状态,如下

[root@2db7f1389dbd /]# exit
exit
[root@centos7 ~]# docker ps
CONTAINER ID   IMAGE  COMMAND   CREATED    STATUS    PORTS   NAMES

3)应用 nsenter 命令进入容器

[root@centos7 ~]# nsenter --help
Usage:
 nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
Options:
 -t, --target <pid>     target process to get namespaces from
 -m, --mount[=<file>]   enter mount namespace
 -u, --uts[=<file>]     enter UTS namespace (hostname etc)
 -i, --ipc[=<file>]     enter System V IPC namespace
 -n, --net[=<file>]     enter network namespace
 -p, --pid[=<file>]     enter pid namespace
 -U, --user[=<file>]    enter user namespace
 -S, --setuid <uid>     set uid in entered namespace
 -G, --setgid <gid>     set gid in entered namespace
     --preserve-credentials do not touch uids or gids
 -r, --root[=<dir>]     set the root directory
 -w, --wd[=<dir>]       set the working directory
 -F, --no-fork          do not fork before exec'ing <program>
 -Z, --follow-context   set SELinux context according to --target PID
 -h, --help     display this help and exit
 -V, --version  output version information and exit

获取容器的 PID

[root@centos7 ~]# docker inspect --format "{{.State.Pid}}" 2db7f1389dbd 
4580
[root@centos7 ~]# nsenter -t 4580 -u -i -n -p
[root@2db7f1389dbd ~]# hostname
2db7f1389dbd
[root@2db7f1389dbd ~]# exit
logout
[root@centos7 ~]# docker ps
CONTAINER ID  IMAGE    COMMAND    CREATED    STATUS   PORTS  NAMES
2db7f1389dbd  centos    "/bin/bash" 22 minutes ago   Up 7 minutes  mgg

4)删除容器

[root@centos7 ~]# docker ps -a
CONTAINER ID   IMAGE  COMMAND   CREATED     STATUS    PORTS    NAMES
2db7f1389dbd  centos  "/bin/bash"  31 minutes ago  Up 16 minutes  mgg
3c113f9a4f1b  centos  "/bin/echo nihao" 38 minutes ago Exited (0) 38 minutes ago boring_liskov
[root@centos7 ~]# docker rm 3c113f9a4f1b  ## 接名称也能够,删除一个进行的容器
3c113f9a4f1b
[root@centos7 ~]# docker rm -f   3c113f9a4f1b ## 删除一个正在运行的容器
[root@centos7 ~]# docker ps -a          
CONTAINER ID  IMAGE   COMMAND    CREATED    STATUS    PORTS   NAMES
2db7f1389dbd    centos    "/bin/bash"    31 minutes ago   Up 16 minutes  mgg
[root@centos7 ~]# docker run --rm centos /bin/echo "hello"   ## 创立时主动删除,用于测试
[root@centos7 ~]#docker --kill $(docker ps -a -q)            ## 删除正在运行的容器

Docker 网络模式

Dokcer 通过应用 Linux 桥接提供容器之间的通信,Docker 的网络模式有四种

别离是以下四种模式:

  • host 模式,应用 –net=host 指定。
  • container 模式,应用 –net=container:NAMEorID 指定。
  • none 模式,应用 –net=none 指定。
  • bridge 模式,应用 –net=bridge 指定,默认配置
  • host 模式

如果容器应用 host 模式,那么容器将不会取得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚构出本人的网卡与配置 IP 等,而是应用宿主机的 IP 和端口。就和间接跑在宿主机中一样。然而容器的文件系统、过程列表等还是和宿主机隔离的。

  • container 模式

这个模式指定新创建的容器和曾经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创立本人的网卡与配置 IP,而是和一个指定的容器共享 IP、端口范畴等。同样,两个容器除了网络方面,其余方面依然是隔离的。

  • none 模式

此模式不同于前两种,Docker 容器有本人的 Network Namespace,然而,Docker 容器没有任何网络配置。而是须要咱们手动给 Docker 容器增加网卡、配置 IP 等。

  • bridge 模式

此模式是 Docker 默认的网络设置,此模式会为每一个容器调配 Network Namespace,并将一个主机上的 Docker 容器连贯到一个虚构网桥上。

更多对于 Docker 容器网络介绍请参考:Docker 容器网络 - 根底篇,Docker 容器网络 - 实现篇。

Docker 数据存储

docker 治理数据的形式有两种:

  • 数据卷
  • 数据卷容器

默认容器的数据是保留在容器的可读写层,当容器被删除时其上的数据也会失落,所以为了实现数据的持久性则须要抉择一种数据长久技术来保留数据。官网提供了三种存储形式:Volumes、Bind mounts 和 tmpfs。

数据存储形式

从当初开始,咱们学习 Docker 容器的数据存储形式,你也能够先理解一下 Docker 数据长久化的三种计划。

Bind mount 会笼罩容器中的文件,而 volume mount 则不会。即如果容器中已有文件,则会将文件同步到主机的目录上。此形式与 Linux 零碎的 mount 形式很类似,即是会笼罩容器内已存在的目录或文件,但并不会扭转容器内原有的文件,当 umount 后容器内原有的文件就会还原。

数据卷(Volumes)

  • 由 docker 创立和治理,且与主机的外围性能隔离

  • 无论是命名还是匿名数据卷,都存储在 /var/lib/docker/volumes/ 上面
  • 定义的数据卷能够在多个容器中同时应用,且不会主动删除
  • 容许容器将内容保留到远端、云服务提供商、加密内容等等

挂在主机目录(Bind mounts)

  • 与数据卷相比,挂在主机目录具备无限的性能
  • 利用的文件或者目录当时不须要存在,用时会主动创立
  • 该形式容许拜访容器的敏感文件,可能会产生安全隐患

内存映射(tmpfs)

  • 仅存储在容器的内存中,永远不会写入文件系统
  • swarm 服务应用 tmpfs 挂载将敏感信息挂载到容器中

数据卷 – volumes

数据卷是存储在 Docker 容器的特定目录上面

劣势阐明

Docker Volumes 机制通常用来给 Docker 容器保留长久化数据,应用 Volumes 有很多劣势:

  • 更容易进行备份和数据迁徙
  • 应用 Docker CLI 命令或者 Docker API 来治理
  • 能够在 Linux 和 Windows 操作系统上应用
  • 能够更平安得在多个容器中共享
  • Volume drivers 容许容器将内容保留到远端、云服务提供商、加密 volume 内容
  • 新 Volume 的内容能够被容器事后填充

Volumes 通常也优于容器的可写层,应用 Volumes 不会减少容器的体积,并且 Volumes 的内容存储在内部独立于容器的生命周期。如果容器不产生长久化数据,能够思考应用 tmpfs 内存映射 (只保留在容器的内存中) 的形式来防止数据存储在其余可能的中央,防止减少容器的体积。

应用阐明

最开始的时候 -v 或者 –volume 选项是给独自容器应用,而 –mount 选项是给集群服务应用。然而从 Docker 17.06 开始,也能够在独自容器上应用 –mount。通常来讲 –mount 选项也更加具体和具体。-v 选项将所有选项集中到一个值,而 –mount 选项将可选项离开。如果须要指定 volume driver 选项,那么必须应用 –mount 选项。

# 创立一个数据卷
$ docker volume create my-vol

# 查看所有的数据卷
$ docker volume ls

# 查看指定数据卷的信息
$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

# 移除指定数据卷的
$ docker volume rm my-vol

# 革除无主的数据卷
$ docker volume prune
# 启动一个挂载数据卷的容器
$ docker run -d -P --name web \
    -v my-vol:/wepapp \
    training/webapp python app.py

$ docker run -d -P --name web \
    --mount source=my-vol,target=/webapp \
    training/webapp python app.py

# 启动一个挂载数据卷的服务
$ docker service create -d --name devtest-service \
    --mount source=myvol2,target=/app \
    nginx:latest
# 挂载为只读模式
$ docker run -d --name=nginxtest \
    -v nginx-vol:/usr/share/nginx/html:ro \
    nginx:latest

# type 能够分为 bind、volume、tmpfs, 默认为 volume
# source 用于设置数据卷的名称,匿名数据卷能够省略
# target 示意须要挂载到容器外面的中央
# readonly 示意挂载的内容为只读模式,可选
# volume-opt 示意能够应用屡次,可选
$ docker run -d --name=nginxtest \
    --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
    nginx:latest
[3] 挂载近程数据卷
# 插件 sshfs 容许您轻松地在容器中挂载近程文件夹

# 下载该插件
$ docker plugin install --grant-all-permissions vieux/sshfs

# 应用该驱动创立 ssh 数据卷
$ docker volume create --driver vieux/sshfs \
    -o sshcmd=test@node2:/home/test \
    -o password=testpassword \
    -o port=3336 \
    sshvolume

# 启动该驱动程序创立卷创立容器
# 如果两个容器配置了可信关系,就不须要设置 volume-opt 明码了
$ docker run -d \
    --name sshfs-container \
    --volume-driver vieux/sshfs \
    --mount src=sshvolume,target=/app, \
    volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
    nginx:latest

挂载主机目录 – bind mounts

挂载主机目录是将主机中的特定目录间接挂在到容器外部应用

应用阐明
# 应用 bind 模式启动容器
$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app \
    nginx:latest

# 看下对应的信息
$ docker inspect devtest
"Mounts": [
    {
        "Type": "bind",
        "Source": "/tmp/source/target",
        "Destination": "/app",
        "Mode": "","RW": true,"Propagation":"rprivate"
    }
]

# 挂载为只读模式
$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app:ro \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app,readonly \
    nginx:latest

非凡属性

$ docker run -d -it --name devtest \
    -v "$(pwd)"/target:/app \
    -v "$(pwd)"/target:/app2:ro,rslave \
    nginx:latest

$ docker run -d -it --name devtest \
    --mount type=bind,source="$(pwd)"/target,target=/app \
    --mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave \
    nginx:latest

内存映射 – tmpfs

内存映射是将内存映射到容器内供容器外部应用

劣势阐明

最开始 –tmpfs 是给独自容器应用,而 –mount 选项是给 swarm 集群服务应用的。然而,从 Docker 17.06 开始,也能够在独自容器上应用 –mount 了。通常说来,–mount 更明确,更简短。最大的区别是 –tmpfs 标记不反对任何可配置选项。其中 –tmpfs 只能在容器中应用,而 swarm 集群则必须应用 –mount 来应用 tmpfs 内存映射。

应用阐明

# 容器上应用
$ docker run -d -it --name tmptest \
    --tmpfs /app \
    nginx:latest

$ docker run -d -it --name tmptest \
    --mount type=tmpfs,destination=/app \
    nginx:latest

日志驱动 – logs

在容器内部查看容器外部的日志输入状况,便于排除和监控问题

能够利用 docker logs 命令,查看 Docker 容器外部利用程序运行时所产生的日志。能够罢黜首先进入 Docker 容器,再关上应用程序的日志文件的过程。docker logs 会监控容器中操作系统的规范输出设备(STDOUT),一旦 STDOUT 有数据产生,就会将这些数据传输到另一个设施中,则被称为日志驱动(Logging Driver)。

# 动静查看日志内容
$ docker logs -f netdata
Docker 是怎么做到的呢?咱们应用 docker info 命令,能够看到 Docker 容器的相干信息,其中有一项 Logging Driver 的字段。# 以后所设置的日志驱动类型
$ docker info | grep 'Logging Driver'
Logging Driver: json-file

咱们能够在 docker run 命令中通过 –log-driver 参数来设置具体的 Docker 日志驱动,也能够通过 –log-opt 参数来指定对应日志驱动的相干选项。

docker run -d -p 80:80 --name nginx \    
--log-driver json-file \ # 设置日志驱动    
--log-opt max-size=10m \ # 示意 JSON 文件最大为 10MB,超过则生成新的文件    
--log-opt max-file=3 \   # 示意 JSON 文件最多保留 3 个,超过则删除多余文件    
nginx
# 当然,能够在配置文件中增加,全局失效
$ cat /etc/docker/daemon.json
{"log-driver": "syslog"}

# 批改配置之后重启服务
$ sudo systemctl restart docker

额定,须要留神的是,默认状况下,Docker 将日志存储到一个日志文件。

# 查看日志文件门路
$ docker inspect --format='{{.LogPath}}' netdata
/var/lib/docker/containers/556553bcb5xxx13cbc588a4-json.log

# 查看实时日志信息
$ tail -f `docker inspect --format='{{.LogPath}}' netdata`

上述内容参考: https://escapelife.github.io/…

Docker Command 介绍

装置实现 docker 容器服务之后,须要理解如何操作它?在 shell 命令行下间接输出 docker 就能够查看帮忙信息,如下。

[root@master ~]# docker
Usage:    docker COMMAND
A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -D, --debug              Enable debug mode
      --help               Print usage
  -H, --host list          Daemon socket(s) to connect to (default [])
  -l, --log-level string   Set the logging level ("debug", "info", "warn", "error", "fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  container   Manage containers
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  volume      Manage volumes

Commands:
  attach      Attach to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

命令很多,重点介绍这 20 个,请具体浏览上面的文章:

这 20 个 Docker Command,有几个是你会的?

Docker file

Docker file 简略介绍

Docker 能够应用 Dockerfile 的内容来主动构建镜像。Dockerfile 也是一个文件,其中有创立镜像、运行指令等一系列的命令,且每行只反对一个运行命令。

Docker file 分为四局部组成:

  • 根底镜像信
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

dockerfile 指令疏忽大小写,倡议大写,# 作为正文,每行只反对一条指令,指令能够带多个参数。

dockerfile 指令有:

  • 构建指令:用于构建 image,其指定的操作不会在运行 image 的容器中执行。
  • 设置指令:用于设置 image 的属性,其指定的操作会在运行 image 的容器中执行。

Dockerfile 指令

Dockerfile 指令一共有以下种:

  • 1、FROM

用来指定根底镜像,而后通过在根底镜像上构建新的镜像,根底镜像个别有近程或本地仓库。并且 Dockerfile 文件第一行必须的 FROM 指令,如果一个 Dockerfile 须要创立多个镜像,能够应用多个 FROM 指令。

# 具体应用用法如下:FROM < image_name >   #默认是 latest 版本
FROM <image:version>  #指定版本
  • 2、MAINTAINER

指定镜像的创建者信息

# 具体应用法如下:MAINTAINER < name >
  • 3、RUN

运行所有根底镜像能反对的命令,同样也能够应用多条 RUN 指令,能够应用 \ 来换行

# 具体应用法如下:RUN < command >
RUN ["executable", "param1", "param2" ...] (exec form) 
  • 4、CMD

用于容器启动时的指定操作,它能够是命令,也能够是脚本,但只执行一次,如果有多少默认只会执行最初一个。

# 具体应用法如下:CMD [“executable”,”Param1”,“param2”]应用 exec 执行,举荐 
CMD command param1 param2,在 /bin/sh 上执行 
CMD [“Param1”,“param2”] 提供给 ENTRYPOINT 做默认参数。
  • 5、EXPOSE

指定容器的端口映射(容器与物理机),运行容器时加上 - p 参数指定 EXPOSE 设置的端口。EXPOSE 能够设置多个端口号,相应地运行容器配套屡次应用 - p 参数。能够通过 docker port + 容器须要映射的端口号和容器 ID 来参考宿主机的映射端口。

# 具体应用法如下:EXPOSE <port> [port1 , port2 ............]
  • 6、ENV

在镜像中用于设置环境变量的,而后 RUN 命令能够应用此设置的环境变量,在容器启动后也以通过 docker inspect 查看环境变量,能够通过 docker run –env key=value 来设置或批改环境变量。

# 具体应用法如下:ENV <key> <value>
ENV JAVA_HOME /usr/local/jdk
  • 7、ADD

复制指定的源文件、目录、URL 到容器的指定目录中。所有拷贝到 container 中的文件和文件夹权限为 0755,uid 和 gid 为 0。

如果源是一个目录,那么会将该目录下的所有文件增加到 container 中,不包含目录;

如果源文件是可辨认的压缩格局,则 docker 会帮忙解压缩(留神压缩格局);

如果源是文件且目标目录中不应用斜杠完结,则会将目标目录视为文件,源的内容会写入目标目录;

如果源是文件且目标目录中应用斜杠完结,则会源文件拷贝到目标目录下。

# 具体应用法如下:ADD < 源 > < 指标 >
  • 8、COPY

复制本地主机的源(默认为 Dockerfile 所在的目录)到容器中的指标中,指标门路不存在时会主动创立。

# 具体应用法如下:COPY < 源 > < 指标 >
COPY web/index.html  /var/web/
  • 门路必须是绝对路径,如果不存在,会主动创立对应目录
  • 门路必须是 Dockerfile 所在门路的相对路径
  • 如果是一个目录,只会复制目录下的内容,而目录自身则不会被复制
  • 9、ENTRYPOINT

指定容器启动后执行的命令,多行只执行最初一行。并且不可被 docker run 提供的参数笼罩。

# 具体应用法如下:ENTRYPOINT "command" "param1" "param2"
  • 10、VOLUME

创立一个能够从本地主机或其它容器挂载的挂载点,个别用于存放数据。与 docker run - v 也能够实现此性能。

# 具体应用法如下:VOLUME  [directory_name]
VOLUME /docker_data
  • 11、USER

指定容器运行时应用的用户或 UID,前面 RUN、CMD、ENTRYPIONT 都会应用此用户来运行命令。

# 具体应用法如下:USER [username/uid]
  • 12、WORKDIR

指定 RUN、CMD、ENTRYPIONT 指定的命令的运行目录。能够应用多个 WORKDIR 指令,后续参数如果是相对路径,则会基于之前的命令指定的门路。如:WORKDIR /data WORKDIR work。最终的门路就是 /data/work。path 门路也能够是环境变量。

# 具体应用办法如下:WORKDIR [path]
  • 13、ONBUILD

配置以后所创立的镜像作为其它新创建镜像的根底镜像时,所执行的操作指令。就是, 这个镜像创立后,如果其它镜像以这个镜像为根底,会先执行这个镜像的 ONBUILD 命令。

# 具体应用法如下:ONBUILD [INSTRUCTION]

通过 Dockerfile 疾速构建镜像

接下来,咱们通过构建一个 Tomcat 镜像,来演示 Dockerfile 的应用办法,前提是装置 Docker 环境,如何装置 Docker 环境就不在此赘述了。请猛戳上面的文字:

[root@master tomcat]# ll
总用量 190504
-rw-r--r-- 1 root root   9552281 6 月   7 15:07 apache-tomcat-8.5.31.tar.gz
-rw-r--r-- 1 root root        32 7 月   3 09:41 index.jsp
-rw-r--r-- 1 root root 185515842 9 月  20 2017 jdk-8u144-linux-x64.tar.gz
[root@master tomcat]# cat index.jsp 
welcome to mingongge's web site
[root@master tomcat]# pwd
/root/docker/tomcat
[root@master tomcat]# vim Dockerfile
#config file start#
FROM centos
MAINTAINER mingongge < 微信公众号: 民工哥技术之路 >

#add jdk and tomcat software
ADD jdk-8u144-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.31.tar.gz /usr/local/
ADD index.jsp /usr/local/apache-tomcat-8.5.31/webapps/ROOT/

#config java and tomcat ENV
ENV JAVA_HOME /usr/local/jdk1.8.0_144
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.31/
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin

#config listen port of tomcat
EXPOSE 8080

#config startup command of tomcat
CMD /usr/local/apache-tomcat-8.5.31/bin/catalina.sh run

#end of config-file#

构建过程

[root@master tomcat]# docker build -t tomcat-web . #这个. 不必正文了吧置信懂的人天然懂的
Sending build context to Docker daemon 195.1 MB
Step 1/11 : FROM centos
 ---> 49f7960eb7e4
Step 2/11 : MAINTAINER mingongge < 微信公众号: 民工哥技术之路 >
 ---> Running in afac1e218299
 ---> a404621fac22
Removing intermediate container afac1e218299
Step 3/11 : ADD jdk-8u144-linux-x64.tar.gz /usr/local/
 ---> 4e22dafc2f76
Removing intermediate container b1b23c6f202a
Step 4/11 : ADD apache-tomcat-8.5.31.tar.gz /usr/local/
 ---> 1efe59301d59
Removing intermediate container aa78d5441a0a
Step 5/11 : ADD index.jsp /usr/local/apache-tomcat-8.5.31/webapps/ROOT/
 ---> f09236522370
Removing intermediate container eb54e6eb963a
Step 6/11 : ENV JAVA_HOME /usr/local/jdk1.8.0_144
 ---> Running in 3aa91b03d2d1
 ---> b497c5482fe0
Removing intermediate container 3aa91b03d2d1
Step 7/11 : ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
 ---> Running in f2649b5069be
 ---> 9cedb218a8df
Removing intermediate container f2649b5069be
Step 8/11 : ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.31/
 ---> Running in 39ef620232d9
 ---> ccab256164fe
Removing intermediate container 39ef620232d9
Step 9/11 : ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
 ---> Running in a58944d03d4a
 ---> f57de761a759
Removing intermediate container a58944d03d4a
Step 10/11 : EXPOSE 8080
 ---> Running in 30681437d265
 ---> b906dcc26584
Removing intermediate container 30681437d265
Step 11/11 : CMD /usr/local/apache-tomcat-8.5.31/bin/catalina.sh run
 ---> Running in 437790cc642a
 ---> 95204158ee68
Removing intermediate container 437790cc642a
Successfully built 95204158ee68

通过构建的镜像启动容器

[root@master tomcat]# docker run -d -p 8080:8080 tomcat-web
b5b65bee5aedea2f48edb276c543c15c913166bf489088678c5a44fe9769ef45
[root@master tomcat]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED        STATUS         PORTS                    NAMES
b5b65bee5aed   tomcat-web   "/bin/sh -c'/usr/..."   5 seconds ago  Up 4 seconds   0.0.0.0:8080->8080/tcp   vigilant_heisenberg

拜访容器

浏览器输出 http://server-ip:8080, 后果如下:

Docker 三剑客

容器技术|Docker 三剑客之 Compose

容器技术|Docker 三剑客之 docker-machine

打造高逼格、可视化的 Docker 容器监控零碎平台

公有镜像仓库搭建

当咱们执行 docker pull xxx 的时候,docker 默认是从 registry.docker.com 这个地址下来查找咱们所须要的镜像文件,而后执行下载操作。这类的镜像仓库就是 docker 默认的公共仓库,所有人都能够间接查看或下载、应用,然而呢,基于网络起因,下载速度有限度比较慢。因而,咱们在公司外部内网环境中应用 dokcer,个别不会将镜像文件上传到公网公共库中。但外部共享应用就是个问题,所以,公有仓库就由此产生了。

什么是公有仓库?

公有仓库,就是本地(内网环境)组建的一个与公网公共库性能类似的镜像仓库。组建好之后,咱们就能够将打包好的镜像提交到公有仓库中,这样内网其它用户也能够应用这个镜像文件。

本文应用官网提供的 registry 镜像来组建企业内网的公有镜像仓库

环境介绍

两台装置好 docker 环境的主机

  • 服务端:192.168.3.82 公有仓库服务器在,运行 registry 容器
  • 客户端:192.168.3.83 测试客户端,用于上传、下载镜像文件

装置布署过程

下载官网 registry 镜像文件

[root@master ~]# docker pull registry
Using default tag: latest
Trying to pull repository docker.io/library/registry ... 
latest: Pulling from docker.io/library/registry
81033e7c1d6a: Pull complete 
b235084c2315: Pull complete 
c692f3a6894b: Pull complete 
ba2177f3a70e: Pull complete 
a8d793620947: Pull complete 
Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54
Status: Downloaded newer image for docker.io/registry:latest
[root@master ~]# docker images |grep registry
docker.io/registry   latest  d1fd7d86a825   5 months ago  33.3 MB

运行 registry 容器

[root@master ~]# mkdir /docker/registry -p
[root@master ~]# docker run -itd -v /docker/registry/:/docker/registry -p 5000:5000 --restart=always --name registry registry:latest
26d0b91a267f684f9da68f01d869b31dbc037ee6e7bf255d8fb435a22b857a0e
[root@master ~]# docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED        STATUS        PORTS                    NAMES
26d0b91a267f   registry:latest  "/entrypoint.sh /e..."   4 seconds ago  Up 3 seconds  0.0.0.0:5000->5000/tcp   registry

参数阐明

1)-itd:在容器中关上一个伪终端进行交互操作,并在后盾运行;2)-v:把宿主机的 /docker/registry 目录绑定到容器 /docker/registry 目录(这个目录是 registry 容器中寄存镜像文件的目录),来实现数据的长久化;3)-p:映射端口;拜访宿主机的 5000 端口就拜访到 registry 容器的服务了;4)--restart=always:这是重启的策略,如果这个容器异样退出会主动重启容器;5)--name registry:创立容器命名为 registry,可自定义任何名称;6)registry:latest:这个是方才 pull 下来的镜像;

查看近程仓库镜像文件

[root@master ~]# curl http://localhost:5000/v2/_catalog
{"repositories":[]}

同样也能够应用浏览器拜访 http://server-ip:5000/v2/_cat… 后果雷同,都是空的没有任何文件。

客户端操作

批改下载的镜像源

[root@slave1 ~]# vim /etc/docker/daemon.json
{"registry-mirrors":["https://registry.docker-cn.com"]
}
[root@slave1 ~]# systemctl restart docker

下载测试镜像

[root@slave1 ~]# docker pull nginx
Using default tag: latest
Trying to pull repository docker.io/library/nginx ... 
latest: Pulling from docker.io/library/nginx
683abbb4ea60: Pull complete 
6ff57cbc007a: Pull complete 
162f7aebbf40: Pull complete 
Digest: sha256:636dd2749d9a363e5b57557672a9ebc7c6d041c88d9aef184308d7434296feea
Status: Downloaded newer image for docker.io/nginx:latest

给镜像打 TAG

[root@slave1 ~]# docker tag nginx:latest 192.168.3.82:5000/nginx:v1
[root@slave1 ~]# docker images
REPOSITORY                TAG       IMAGE ID        CREATED       SIZE
192.168.3.82:5000/nginx   v1        649dcb69b782    8 hours ago   109 MB
docker.io/nginx           latest    649dcb69b782    8 hours ago   109 MB

上传镜像

[root@slave1 ~]# docker push 192.168.3.82:5000/nginx:v1
The push refers to a repository [192.168.3.82:5000/nginx]
Get https://192.168.3.82:5000/v1/_ping: http: server gave HTTP response to HTTPS client
#留神这里呈现报错提醒,从提示信息能够看出须要应用 https 的形式能力上传,解决方案如下:[root@slave1 ~]# vim /etc/docker/daemon.json
{"registry-mirrors":["https://registry.docker-cn.com"],
 "insecure-registries":["192.168.3.82:5000"]
}
#增加公有镜像服务器的地址,留神书写格局为 json,有严格的书写要求,须要重启 docker 服务失效配置
[root@slave1 ~]# systemctl restart docker
[root@slave1 ~]# docker push 192.168.3.82:5000/nginx:v1
The push refers to a repository [192.168.3.82:5000/nginx]
6ee5b085558c: Pushed 
78f25536dafc: Pushed 
9c46f426bcb7: Pushed 
v1: digest: sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7 size: 948

从新查看镜像仓库

[root@master ~]# curl http://localhost:5000/v2/_catalog
{"repositories":["nginx"]}
[root@master ~]# curl http://localhost:5000/v2/nginx/tags/list
{"name":"nginx","tags":["v1"]}
#查看有哪些版本

测试下载

# 首先删除客户端主机之前从公共库下载下来的镜像文件
[root@slave1 ~]# docker images
REPOSITORY                TAG      IMAGE ID        CREATED        SIZE
192.168.3.82:5000/nginx   v1       649dcb69b782    10 hours ago   109 MB
docker.io/nginx           latest   649dcb69b782    10 hours ago   109 MB
[root@slave1 ~]# docker image rmi -f 649dcb69b782
Untagged: 192.168.3.82:5000/nginx:v1
Untagged: 192.168.3.82:5000/nginx@sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7
Untagged: docker.io/nginx:latest
Untagged: docker.io/nginx@sha256:636dd2749d9a363e5b57557672a9ebc7c6d041c88d9aef184308d7434296feea
Deleted: sha256:649dcb69b782d4e281c92ed2918a21fa63322a6605017e295ea75907c84f4d1e
Deleted: sha256:bf7cb208a5a1da265666ad5ab3cf10f0bec1f4bcb0ba8d957e2e485e3ac2b463
Deleted: sha256:55d02c20aa07136ab07ab47f4b20b97be7a0f34e01a88b3e046a728863b5621c
Deleted: sha256:9c46f426bcb704beffafc951290ee7fe05efddbc7406500e7d0a3785538b8735
[root@slave1 ~]# docker images
REPOSITORY       TAG             IMAGE ID        CREATED         SIZE
#此时客户端所有的镜像文件全副删除
[root@slave1 ~]# docker pull 192.168.3.82:5000/nginx:v1
Trying to pull repository 192.168.3.82:5000/nginx ... 
v1: Pulling from 192.168.3.82:5000/nginx
683abbb4ea60: Pull complete 
6ff57cbc007a: Pull complete 
162f7aebbf40: Pull complete 
Digest: sha256:edad5e71815c79108ddbd1d42123ee13ba2d8050ad27cfa72c531986d03ee4e7
Status: Downloaded newer image for 192.168.3.82:5000/nginx:v1
[root@slave1 ~]# docker images
REPOSITORY                TAG     IMAGE ID       CREATED         SIZE
192.168.3.82:5000/nginx   v1      649dcb69b782   11 hours ago    109 MB
#能够看出,客户端已失常从远端服务器拉取到所须要的镜像文件,其它内网服务器也能够失常共享这台镜像服

以上步骤就是通过应用 docker Registry 疾速搭建公有镜像仓库的过程与测试。我也其实也能够通过:利用 Harbor 搭建企业级公有镜像仓库。

Docker 可视化工具

Docker 是一项十分风行的容器技术,当初在各行各业有着宽泛的应用。不过如何治理 Docker 容器是一个问题,所以我明天向大家介绍两款 Docker 可视化工具,心愿对大家有所帮忙。

Portainer

Portainer 是一款 Docker 可视化管理工具,容许咱们在网页中不便的查看和治理 Docker 容器。

要应用 Portainer 很简略,运行上面两条命令即可。这些命令会创立一个 Portainer 专用的卷,而后在 8000 和 9000 端口创立容器并运行。

$ docker volume create portainer_data$ docker run --name portainer -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

而后在浏览器关上对应地址,就会发现胜利运行了。第一次运行的时候须要设置账号,而后抉择要治理的 Docker 主机。

设置账号

抉择要治理的主机

之后就能够看到本机上运行的 Docker 容器了,点击它们还能够进行容器的治理。右边的条目能够治理卷、创立容器、查看主机信息等等。基本上该有的性能都有了,这也是我举荐的一个工具。

LazyDocker

LazyDocker 是基于终端的一个可视化查问工具,反对键盘操作和鼠标点击。相比 Portainer 来说可能不那么业余,不过对于开发者来说可能反而更加好用了。因为个别开发者都是应用命令行来运行 Docker,偶然须要图形化查看的时候,就能够应用 LazyDocker 这个工具。

官网演示图

装置 LazyDocker 也非常简单,运行上面的命令即可。

docker run --rm -it -v \/var/run/docker.sock:/var/run/docker.sock \-v ~/.config/lazydocker:/.config/jesseduffield/lazydocker \lazyteam/lazydocker

当然如果发现 LazyDocker 挺好用,筹备常常应用的话,还能够把它做成缩写增加到 shell 配置文件中,这样就能够将它变成一个简略的命令。例如我用的是 zsh,就将上面这样增加到.zshrc 文件中。当前就能够间接用 lzd 来调用 LazyDocker 了。

alias lzd='docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker lazyteam/lazydocker'

而后就能够在终端中查看 Docker 容器、镜像和卷的信息了。LazyDocker 反对键盘操作和鼠标点击,间接用鼠标点击就能够查看对应信息了。

须要留神如果你的终端 LazyDocker 的图形显示的是乱的,不必放心,只不过是显示字体的问题。从新设置一下终端字体就能够解决了。

以上内容来自:https://www.toutiao.com/i6780…

Docker 社区曾经创立了许多开源工具,它们能帮咱们解决各种用例。作者在本文中举荐了 5 款认为最有用的 Docker 工具,别离是 Watchtower(自动更新 Docker 容器)、docker-gc(容器和镜像的垃圾回收)、docker-slim(容器瘦身)、rocker:冲破 Dockerfile 的限度,以及 ctop(容器的类顶层接口)。
Docker 社区曾经创立了许多开源工具,它们所能帮你解决的用例甚至会超出你的设想。
你能够在网上找到很多酷炫的 Docker 工具,其中大部分是开源的,都能够在 Github 上找到。在过来的两年里,我十分热衷于 Docker,在大多数开发我的项目中都应用了它。当你开始应用 Docker 后,你会发现它实用的场景比你最后料想的还更多。你会心愿 Docker 尽可能为你多做一点事,而它不会让你悲观的!
Docker 社区十分沉闷,每天都会呈现许多有用的工具,时时关注社区中产生的所有翻新是很艰难的。为了帮忙你,我收集了一些我在日常工作中应用的又乏味又实用的 Docker 工具,这些工具晋升了我的工作效率,缩小了本来须要手工实现的工作。

向大家举荐一些实用工具: 你应该晓得的 5 个开源 Docker 工具 …,Docker 服务终端 UI 管理工具,大家最终依据本人的应用习惯与理论生产需要来抉择适合本人的工具来治理 Docker 容器。

Docker 容器监控零碎

随着线上服务的全面 docker 化,对 docker 容器的监控就很重要了。SA 的监控零碎是物理机的监控,在一个物理机跑多个容器的状况下,咱们是没法从一个监控图表外面辨别各个容器的资源占用状况的。

举荐大家看看这篇:打造高逼格、可视化的 Docker 容器监控零碎平台

Docker 日志治理最佳实际

10 个冷门但又十分实用的 Docker 应用技巧

在平时的工作中,docker 接触得很多,除了常常应用的 docker run,docker stop 等命令,docker 还有很多非常有用然而却不常常应用的命令,上面就来总结一下:

1. docker top

这个命令是用来查看一个容器外面的过程信息的,比方你想查看一个 nginx 容器外面有几个 nginx 过程的时候,就能够这么做:

docker top 3b307a09d20d
UID      PID    PPID    C    STIME  TTY    TIME       CMD
root     805    787     0    Jul13   ?   00:00:00  nginx: master process nginx -g daemon off;
systemd+ 941     805     0   Jul13    ?   00:03:18  nginx: worker process

2. docker load && docker save

我个别应用这两个命令去下载打包 Kubernetes 的镜像,因为你晓得的国内的网速并不像国外那么快。

docker save 能够把一个镜像保留到 tar 文件中,你能够这么做:

~ docker save registry:2.7.1 >registry-2.7.1.tar
#同时 docker load 能够把镜像从 tar 文件导入到 docker 中
~ docker load < registry-2.7.1.tar

3. docker search

这个命令能够帮忙你在命令行中不便的搜寻 DockerHub 中的镜像,比方:

~ docker search nginx
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                              Official build of Nginx.                        13519               [OK]
jwilder/nginx-proxy                Automated Nginx reverse proxy for docker con…   1846                                    [OK]
richarvey/nginx-php-fpm            Container running Nginx + PHP-FPM capable of…   780                                     [OK]
linuxserver/nginx                  An Nginx container, brought to you by LinuxS…   123
bitnami/nginx                      Bitnami nginx Docker Image                      87                                      [OK]
tiangolo/nginx-rtmp                Docker image with Nginx using the nginx-rtmp…   85                                      [OK]
jc21/nginx-proxy-manager           Docker container for managing Nginx proxy ho…   73
alfg/nginx-rtmp                    NGINX, nginx-rtmp-module and FFmpeg from sou…   71                                      [OK]
nginxdemos/hello                   NGINX webserver that serves a simple page co…   57                                      [OK]
jlesage/nginx-proxy-manager        Docker container for Nginx Proxy Manager        53                                      [OK]
nginx/nginx-ingress                NGINX Ingress Controller for Kubernetes         37
......

当然这个性能在国内可能不会特地好用,因为 ……

4. docker events

这个命令能够帮忙你实时获取 docker 的各种事件信息,比方创立了一个容器什么的。

~ docker events
2020-07-28T21:28:46.000403018+08:00 image load sha256:432bf69f0427b52cad10897342eaf23521b7d973566354118e9a59c4d31b5fae (name=sha256:432bf69f0427b52cad10897342eaf23521b7d973566354118e9a59c4d31b5fae)

5. docker update

当你 docker run 了之后却发现外面有一些参数并不是你想要的状态比方你设置的 nginx 容器 cpu 或者内存太小,这个时候你就能够应用 docker update 去批改这些参数。

~ docker update nginx --cpus 2

6. docker history

当你批改了一个镜像,然而遗记了每一层的批改命令,或者你想查看一个镜像是怎么构建的时候就能够应用这个命令,比方:

~ docker history  traefik:v2.1.6
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
5212a87ddaba        5 months ago        /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>           5 months ago        /bin/sh -c #(nop)  CMD ["traefik"]              0B
<missing>           5 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["/entrypoint.…   0B
<missing>           5 months ago        /bin/sh -c #(nop)  EXPOSE 80                    0B
<missing>           5 months ago        /bin/sh -c #(nop) COPY file:59a219a1fb7a9dc8…   419B
<missing>           5 months ago        /bin/sh -c set -ex;  apkArch="$(apk --print-…   52.9MB
<missing>           5 months ago        /bin/sh -c apk --no-cache add ca-certificate…   1.85MB
<missing>           6 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           6 months ago        /bin/sh -c #(nop) ADD file:a1906f14a4e217a49…   4.81MB

7. docker wait

这个命令能够查看容器的退出状态,比方:

~ docker wait 7f7f0522a7d0
0

这样你就能够晓得这个容器是失常退出的还是异样退出的了。

8. docker pause && docker unpause

当你运行了一个容器然而想要暂停它运行的时候,你就能够应用这个命令。

~ docker pause 7f7f0522a7d0

9. docker diff

当你运行了一个容器,然而你不晓得容器里批改了哪一些文件的时候能够应用这个命令,比方:

~ docker diff 38c59255bf6e
C /etc
A /etc/localtime
C /var
C /var/lib
A /var/lib/registry

10. docker stats

这个是 docker 内置的监控命令,当你想要查看以后主机下所有容器占用内存和 cpu 的状况的时候就能够应用这个命令。

~ docker stats

CONTAINER ID        NAME                        CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
1c5ade04e7f9        redis                        0.08%               17.53MiB / 47.01GiB   0.04%               10.9GB / 37GB       0B / 0B             4
afe6d4ebe409        kafka-exporter                0.09%               16.91MiB / 47.01GiB   0.04%               1.97GB / 1.53GB     752MB / 0B          23
f0c7c01a9c34        kafka-docker_zookeeper         0.01%               308.8MiB / 47.01GiB   0.64%               20.2MB / 12.2MB     971MB / 3.29MB      28
da8c5008955f        kafka-docker_kafka-manager     0.08%               393.2MiB / 47.01GiB   0.82%               1.56MB / 2.61MB     1.14GB / 0B         60
c8d51c583c49        kafka-docker_kafka            1.63%               1.256GiB / 47.01GiB   2.67%               30.4GB / 48.9GB     22.3GB / 5.77GB     85
......

原文:http://suo.im/6n2lLa

学习 Docker,老手最容易犯的 11 个谬误!

很多人最终还是决定应用 Docker 解决问题。Docker 的长处很多,比方:

  • 1、一体化——将操作系统、库版本、配置文件、应用程序等全部打包装在容器里。从而保障 QA 所测试的镜像 (image) 会携带同样的行为达到生产环境。
  • 2、轻量——内存占用极小,只为次要过程分配内存。
  • 3、快读——一键启动,就像启动常见的 linux 过程一样快。

尽管如此,泛滥用户依然只是把容器当做常见的虚拟机,而遗记了容器的一个重要个性:
正因为这一特点,一些用户须要扭转他们对容器的观点,为了更好的应用与施展 Docker 容器的价值,有一些事件是相对不应该做的:

1. 不要在容器(container)中存储数据

容器可能会被中断、被替换或受到毁坏。在容器中运行的 1.0 版应用程序很容易就会被 1.1 版取代,而不会对数据造成影响或导致数据失落。因而,如果须要存储数据,请存储在卷 (volume) 中。在这一状况下,还应留神两个容器是否会在同一个卷上写入数据,这将导致损坏。请确保应用程序实用于写入共享的数据存储。

2. 不要分两局部传送应用程序 有些人把容器当作虚拟机

所以他们大多会认为,应该将应用程序部署到现有正在运行的容器中。在须要一直部署和调试的开发阶段,可能的确如此;但对于 QA 和生产的继续交付 (CD) 渠道,应用程序该当是镜像的一部分。切记:容器转瞬即逝。

3. 不要创立大尺寸镜像

大尺寸的镜像难以调配。请确保仅应用必须文件和库来运行应用程序。不要装置不必要的数据包,也不要运行“更新”(yum update),这些操作会把大量文件下载到新的镜像层。

4. 不要应用单层镜像

为了无效利用多层文件系统,请始终为操作系统创立属于本人的根本镜像层,而后为用户名定义创立一个层,为运行时装置创立一个层,为配置创立一个层,最初再为应用程序创立一个层。这样,从新创立、治理和调配镜像就会容易些。

5. 不要从正在运行的容器中创立镜像

换句话说,不要应用 ”docker commit” 命令来创立镜像。这一镜像创立办法不可复制,因而应完全避免应用。请始终应用 Dockerfile 或其余任何可齐全复制的 S21(从源代码到镜像)办法,如此一来,如果存储在源代码管制存储库 (GIT) 中,就能够跟踪 Dockerfile 的变更状况。

6. 不要只应用“最新版”标签

最新版标签就像 Maven 用户的“快照”(SNAPSHOT) 一样。容器具备多层文件系统这一基本特征,所以咱们激励应用标签。置信谁也不违心在构建了几个月的镜像后,忽然发现应用程序因为父层(即 Dockerfile 中的 FROM)被新版本取代而无奈运行(新版本无奈向后兼容或从构建缓存中检索的“最新“版有误)这样的意外吧?在生产过程中部署容器时也应防止应用”最新版“标签,这是因为无奈跟踪以后运行的镜像版本。

7. 不要在单个容器中运行一个以上过程

容器只运行一个过程(HTTP 守护过程、应用程序服务器、数据库)时成果最佳,但如果运行一个以上过程,在治理和检索日志以及独自更新过程时就会遇到很多麻烦。

8. 不要在镜像中存储证书及应用环境变量

不要在镜像中对任何用户名 / 明码进行硬编码操作。请应用环境变量从容器内部检索信息。Postgres 镜像就是这一原理的极佳诠释。

9. 不要以 root 权限运行过程

“默认状况下,Docker 容器以 root 用户权限运行。随着 Docker 技术日趋成熟,可能应用的平安默认选项越来越多。目前,要求 root 对其余用户来说较为危险,另外,不是所有环境都可能应用 root。镜像应应用 USER 指令来为容器的运行指定非 root 用户。”(摘自《Docker 镜像作者指南》(Guidance for Docker Image Authors))

10. 不要依赖 IP 地址

每个容器都有本人的外部 IP 地址,如果启动而后进行容器,外部 IP 地址可能会发生变化。如果你的应用程序或微服务须要和另一个容器进行通信,请应用环境变量在容器之间传递相应的主机名和端口。

11. 监控容器 Docker

监控曾经越来越受到开发者们的器重,实时监控 Docker 的办法,这里举荐 Cloudinsight。不同于一些须要自写脚本的监控伎俩,Cloudinsight 作为一家收费的 SaaS 服务,可能一键监控 Docker,且领有很棒的可视化界面。除此之外,Cloudinsight 还反对多种操作系统、数据库等的监控,可能一体化展现所有被监控的零碎根底组件的性能数据。

原文:https://my.oschina.net/cllgee…

Jenkins 与 Docker 的自动化 CI/CD 实战

一、公布流程设计

工作流程:

  • 开发人员提交代码到 Git 版本仓库;
  • Jenkins 人工 / 定时触发我的项目构建;
  • Jenkins 拉取代码、代码编码、打包镜像、推送到镜像仓库;
  • Jenkins 在 Docker 主机创立容器并公布。

三、部署过程

1, 部署 git

如果公司外部有间接克隆就能够

git clone git@192.168.0.31:/home/git/solo.git

2,部署 Jenkins 环境

部署传送门:Jenkins+Maven+Svn 实现代码主动打包与公布

3,部署公有镜像仓库

留神:docker 仓库 因为 https 认证,所有须要 pull 的客户端,须要批改配置文件

[root@linux-node1 ~]# vim /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
 OPTIONS='--selinux-enabled --insecure-registry 192.168.56.11:5000'

4,所有主机装置 docker

1)装置依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2`
 
2)增加 Docker 软件包源:yum-config-manager 
--add-repo 
https://download.docker.com/linux/centos/docker-ce.repo

3)装置 Docker CE
 yum install docker-ce -y`
 
4)配置加速器
 curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://bc437cce.m.daocloud.io`
 #因为默认源会去国外获取数据,所以会慢能够超时,这是咱们就须要配置加速器指向国内源 https://www.daocloud.io/
 
5)启动并开机启动
# systemctl start docker
# systemctl enable docker

四、构建根底镜像

【Apache、Nginx、Tomcat、LNMP、LAMP、LNTP】

JAVA 程序必须有 JDK 环境才能够运行,为了缩小镜像大小及进步性能,这里间接把 JDK 放到宿主机上,容器以挂载模式应用。

1,装置 jdk

#rz 把 tar 包上传,解压后放到指定目录
rz....... 
tar -zxvf jdk-8u60-linux-x64.tar.gz
mv jdk1.8.0_60 /usr/local/jdk1.8

2,拟写 Dockerfile

# cat Dockerfile
FROM centos:7
#他的妈妈是谁
MAINTAINER www.aliangedu.com
#他的爸爸是谁
ENV VERSION=8.5.33
#tomcat 版本
ENV JAVA_HOME /usr/local/jdk
#jdk 绝对路径
RUN yum install wget -y
#运行的命令
RUN wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && 
 tar zxf apache-tomcat-${VERSION}.tar.gz && 
 mv apache-tomcat-${VERSION} /usr/local/tomcat && 
 rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && 
 mkdir /usr/local/tomcat/webapps/ROOT
EXPOSE 8080
#程序应用的端口
CMD /usr/local/tomcat/bin/catalina.sh run
#执行 tomcat 目录下的启动脚本,这外面遇到坑,就是 -v 将宿主机 jdk 目录挂在到容器 /usr/local/jdk 时候,因为镜像依照 dockerfile 去打,那么在执行命令的时候就会找不到门路,所以我长期删除了,EXPOSE 与 CMD 2 行,而后从新打包,应用 -p 指定端口,而后进入容器,手工启动 tomcat 的形式,进行

3,构建镜像

docker build -t 192.168.56.11:5000/tomcat-85:latest -f dockerfile . 
#最初这个点。代表以后门路,在制作镜像时,会记录上下文内容

4,上传到 docker 镜像仓库

root@node02 scripts]# docker push 192.168.56.11:5000/tomcat-85:latest 

5,启动镜像 测试

[root@node02 scripts]# docker run -it -d -p 8080:8080 -v /usr/local/jdk1.8:/usr/local/jdk 192.168.56.11:5000/tomcat-8:latest
[root@3addff07c464 ROOT]# echo "123" >index.jsp

五、Jenkins 配置

1. 主页面 -> 系统管理 -> 全局工具配置

指定 JDK、Maven 门路,Git 放弃默认:

2.jenkins 装置必要插件

主页面 -> 系统管理 -> 治理插件:

装置 SSH 与 Git Parameter 插件。

插件阐明:

  • 》SSH:用于 SSH 近程 Docker 主机执行 Shell 命令
  • 》Git Parameter:动静获取 Git 仓库 Branch、Tag

3,配置 SSH 插件

第一步:先创立一个用于连贯 Docker 主机的凭证(有权限的用户)

主页面 -> 凭据 -> 零碎 -> 右击全局凭据 -> 增加凭据:

输出连贯 Docker 主机的用户名和明码:

第二步:增加 SSH 近程主机

主页面 -> 系统管理 -> 零碎设置 -> SSH remote hosts:

问题:当以普通用户身份去应用 docker images 时,呈现以下谬误:

六、将从 github 上下载的 JAVA 我的项目,上传到本人的 gitlab 仓库

# git clone https://github.com/b3log/solo
# cd solo
移除旧的推送地址,增加新的:# git remote remove origin 
# git remote add origin git@gitlab.example.com:qqq/solo.git
提交代码到 Git 仓库并创立 tag:# touch src/main/webapp/a.html
# git add .
# git commit -m“a”创立标签:# git tag 1.0.0
推送到 Git 服务器:# git push origin 1.0.0 

登陆 gitlab 查看 solo 我的项目:

七、Jenkins 创立我的项目并公布测试

1. 主页面 -> 新建工作 -> 输出工作名称,构建一个 Maven 我的项目:

留神:如果没有显示“构建一个 Maven 我的项目”选项,须要在治理插件里装置“Maven Integration plugin”插件。

配置 Git 参数化构建:

2. 动静获取 Git 仓库 tag,与用户交互抉择 Tag 公布:【也能够设置分支】

3. 指定我的项目 Git 仓库地址:

批改 */master 为 $Tag,Tag 是下面动静获取的变量名,示意依据用户抉择打代码版本。

4. 设置 maven 构建命令选项:

clean package -Dmaven.test.skip=ture

利用 pom.xml 文件构建我的项目。

在 Jenkins 本机镜像构建与推送到镜像仓库,并 SSH 近程连贯到 Docker 主机应用推送的镜像创立容器:

上图中 命令内容如下:

REPOSITORY=192.168.56.11:5000/solo:${Tag}
# 构建镜像
cat > Dockerfile << EOF
FROM 192.168.56.11:5000/tomcat-8:latest
RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY target/*.war /usr/local/tomcat/webapps/ROOT.war
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
EOF
docker build -t $REPOSITORY .
# 上传镜像
docker push $REPOSITORY


上图中 Command 内容如下:

REPOSITORY=192.168.56.11:5000/solo:${Tag}
# 部署
sudo docker rm -f blog-solo |true
sudo docker image rm $REPOSITORY |true
sudo docker container run -d --name blog-solo -v /usr/local/jdk1.8:/usr/local/jdk -p 8080:8080 $REPOSITORY
# -d 后盾运行,-v 挂在目录,-p 映射端口,前面是镜像

注:容器名称 blog-solo,裸露宿主机端口 8080,即应用宿主机 IP 192.168.56.12:8080 拜访 blog-solo 我的项目。

blog-solo 我的项目已配置实现,开始构建:

抉择 tag,开始构建:

点击左下角构建历史里,右击第一个查看控制台输入:

构建具体内容

构建胜利

拜访:192.168.56.12:8080 查看部署后果

调整我的项目拜访地址

进入容器,切换到我的项目目录

vi WEB-INF/classes/latke.properties 
#### Server ####
# Browser visit protocol
serverScheme=http
# Browser visit domain name
serverHost=192.168.56.12
# Browser visit port, 80 as usual, THIS IS NOT SERVER LISTEN PORT!
serverPort=8080

调整后,重启 tomcat,再次验证,OK,后果如下:

至此,自动化 CI 环境搭建实现,你能够模仿提交代码并打 tag 测试自动化公布流程。

八、问题总结:

查看 docker.sock 权限

[root@node03 ~]# ll /var/run/docker.sock 
srw-rw---- 1 root docker 0 9 月 4 21:55 /var/run/docker.sock

解决办法:【免 sudo 应用 docker images】

[root@node03 ~]# sudo groupadd docker
 ##groupadd:“docker”组已存在
[root@node03 ~]# sudo gpasswd -a jenkins docker
 ## 正在将用户“jenkins”退出到“docker”组中
[root@node03 ~]# sudo service docker restart
## 重启服务
[root@node03 ~]# newgrp - docker
## 从新加载 group 组信息,肯定要输出这条命令,否则无奈加载最新组内容,因为有缓存

原文:https://www.toutiao.com/a6602…

应用 GitLab CI 和 Docker 主动部署 Spring Boot 利用

Docker 常见疑难杂症解决方案

这里次要是为了记录在应用 Docker 的时候遇到的问题及其解决解决办法。

1.Docker 迁徙存储目录

默认状况零碎会将 Docker 容器寄存在 /var/lib/docker 目录下

问题起因: 明天通过监控零碎,发现公司其中一台服务器的磁盘快慢,随即下来看了下,发现 /var/lib/docker 这个目录特地大。由上述起因,咱们都晓得,在 /var/lib/docker 中存储的都是相干于容器的存储,所以也不能轻易的将其删除掉。

那就筹备迁徙 docker 的存储目录吧,或者对 /var 设施进行扩容来达到雷同的目标。更多对于 dockerd 的具体参数,请点击查看 官网文档 地址。

然而须要留神的一点就是,尽量不要用软链,因为一些 docker 容器编排零碎不反对这样做,比方咱们所熟知的 k8s 就在内。

# 发现容器启动不了了
ERROR:cannot  create temporary directory!
# 查看零碎存储状况
$ du -h --max-depth=1

解决办法 1:增加软链接

# 1. 进行 docker 服务
$ sudo systemctl stop docker
# 2. 开始迁徙目录
$ sudo mv /var/lib/docker /data/
# 3. 增加软链接
# sudo ln -s /data/docker /var/lib/docker
# 4. 启动 docker 服务
$ sudo systemctl start docker

解决办法 2:改变 docker 配置文件

# 3. 改变 docker 启动配置文件
$ sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --graph=/data/docker/
# 4. 改变 docker 启动配置文件
$ sudo vim /etc/docker/daemon.json
{
    "live-restore": true,
    "graph": ["/data/docker/"]
}

操作注意事项:在迁徙 docker 目录的时候留神应用的命令,要么应用 mv 命令间接挪动,要么应用 cp 命令复制文件,然而须要留神同时复制文件权限和对应属性,不然在应用的时候可能会存在权限问题。如果容器中,也是应用 root 用户,则不会存在该问题,然而也是须要依照正确的操作来迁徙目录。

# 应用 mv 命令
$ sudo mv /var/lib/docker /data/docker
# 应用 cp 命令
$ sudo cp -arv /data/docker /data2/docker

下图中,就是因为启动的容器应用的是普通用户运行过程的,且在运行当中须要应用 /tmp 目录,后果提醒没有权限。在咱们导入容器镜像的时候,其实是会将容器启动时须要的各个目录的权限和属性都赋予了。如果咱们间接是 cp 命令单纯复制文件内容的话,就会呈现属性不统一的状况,同时还会有肯定的平安问题。

2.Docker 设施空间有余

Increase Docker container size from default 10GB on rhel7.

问题起因一:容器在导入或者启动的时候,如果提醒磁盘空间有余的,那么多半是真的因为物理磁盘空间真的有问题导致的。如下所示,咱们能够看到 / 分区的确满了。

# 查看物理磁盘空间
$ df -Th
Filesystem    Size    Used    Avail    Use%    Mounted on
/dev/vda1      40G     40G       0G    100%    /
tmpfs         7.8G       0     7.8G      0%    /dev/shm
/dev/vdb1     493G    289G     179G     62%    /mnt

如果发现真的是物理磁盘空间满了的话,就须要查看到底是什么占据了如此大的空间,导致因为容器没有空间无奈启动。其中,docker 自带的命令就是一个很好的可能帮忙咱们发现问题的工具。

# 查看根本信息
# 硬件驱动应用的是 devicemapper,空间池为 docker-252
# 磁盘可用容量仅剩 16.78MB,可用供咱们应用
$ docker info
Containers: 1
Images: 28
Storage Driver: devicemapper
 Pool Name: docker-252:1-787932-pool
 Pool Blocksize: 65.54 kB
 Backing Filesystem: extfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 1.225 GB
 Data Space Total: 107.4 GB
 Data Space Available: 16.78 MB
 Metadata Space Used: 2.073 MB
 Metadata Space Total: 2.147 GB

解决办法:通过查看信息,咱们晓得正是因为 docker 可用的磁盘空间有余,所以导致启动的时候没有足够的空间进行加载启动镜像。解决的办法也很简略,第一就是清理有效数据文件开释磁盘空间(革除日志),第二就是批改 docker 数据的寄存门路(大分区)。

# 显示哪些容器目录具备最大的日志文件
$ du -d1 -h /var/lib/docker/containers | sort -h
# 革除您抉择的容器日志文件的内容
$ cat /dev/null > /var/lib/docker/containers/container_id/container_log_name

问题起因二:显然我遇到的不是上一种状况,而是在启动容器的时候,容器启动之后不久就显示是 unhealthy 的状态,通过如下日志发现,原来是复制配置文件启动的时候,提醒磁盘空间有余。

前面发现是因为 CentOS7 的零碎应用的 docker 容器默认的创立大小就是 10G 而已,然而咱们应用的容器却超过了这个限度,导致无奈启动时提醒空间有余。

2019-08-16 11:11:15,816 INFO spawned: 'app-demo' with pid 835
2019-08-16 11:11:16,268 INFO exited: app (exit status 1; not expected)
2019-08-16 11:11:17,270 INFO gave up: app entered FATAL state, too many start retries too quickly
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device
cp: cannot create regular file '/etc/supervisor/conf.d/grpc-app-demo.conf': No space left on device

解决办法 1:改变 docker 启动配置文件

# /etc/docker/daemon.json
{
    "live-restore": true,
    "storage-opt": ["dm.basesize=20G"]
}

解决办法 2:改变 systemctl 的 docker 启动文件

# 1.stop the docker service
$ sudo systemctl stop docker
# 2.rm exised container
$ sudo rm -rf /var/lib/docker
# 2.edit your docker service file
$ sudo vim /usr/lib/systemd/system/docker.service
# 3.find the execution line
ExecStart=/usr/bin/dockerd
and change it to:
ExecStart=/usr/bin/dockerd --storage-opt dm.basesize=20G
# 4.start docker service again
$ sudo systemctl start docker
# 5.reload daemon
$ sudo systemctl daemon-reload

问题起因三:还有一种状况也会让容器无奈启动,并提醒磁盘空间有余,然而应用命令查看发现并不是因为物理磁盘真的有余导致的。而是,因为对于分区的 inode 节点数满了导致的。

# 报错信息
No space left on device

解决办法:因为 ext3 文件系统应用 inode table 存储 inode 信息,而 xfs 文件系统应用 B+ tree 来进行存储。思考到性能问题,默认状况下这个 B+ tree 只会应用前 1TB 空间,当这 1TB 空间被写满后,就会导致无奈写入 inode 信息,报磁盘空间有余的谬误。咱们能够在 mount 时,指定 inode64 即可将这个 B+ tree 应用的空间扩大到整个文件系统。

# 查看零碎的 inode 节点应用状况
$ sudo df -i
# 尝试从新挂载
$ sudo mount -o remount -o noatime,nodiratime,inode64,nobarrier /dev/vda1

补充常识:文件贮存在硬盘上,硬盘的最小存储单位叫做“扇区”(Sector)。每个扇区贮存 512 字节(相当于 0.5KB)。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性间断读取多个扇区,即一次性读取一个“块”(block)。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是 4KB,即间断八个 sector 组成一个 block 块。文件数据都贮存在”块”中,那么很显然,咱们还必须找到一个中央贮存文件的元信息,比方文件的创建者、文件的创立日期、文件的大小等等。这种贮存文件元信息的区域就叫做“索引节点”(inode)。每一个文件都有对应的 inode,外面蕴含了除了文件名以外的所有文件信息。

inode 也会耗费硬盘空间,所以硬盘格式化的时候,操作系统主动将硬盘分成两个区域。一个是数据区,寄存文件数据;另一个是 inode 区(inode table),寄存 inode 所蕴含的信息。每个 inode 节点的大小,个别是 128 字节或 256 字节。inode 节点的总数,在格式化时就给定,个别是每 1KB 或每 2KB 就设置一个 inode 节点。

# 每个节点信息的内容
$ stat check_port_live.sh
  File: check_port_live.sh
  Size: 225           Blocks: 8          IO Block: 4096   regular file
Device: 822h/2082d    Inode: 99621663    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (1006/  escape)   Gid: (1006/  escape)
Access: 2019-07-29 14:59:59.498076903 +0800
Modify: 2019-07-29 14:59:59.498076903 +0800
Change: 2019-07-29 23:20:27.834866649 +0800
 Birth: -
# 磁盘的 inode 应用状况
$ df -i
Filesystem                 Inodes   IUsed     IFree IUse% Mounted on
udev                     16478355     801  16477554    1% /dev
tmpfs                    16487639    2521  16485118    1% /run
/dev/sdc2               244162560 4788436 239374124    2% /
tmpfs                    16487639       5  16487634    1% /dev/shm

3.Docker 缺共享链接库

Docker 命令须要对 /tmp 目录上面有拜访权限

问题起因:给零碎装置完 compose 之后,查看版本的时候,提醒短少一个名为 libz.so.1 的共享链接库。第一反馈就是,是不是零碎少装置那个软件包导致的。随即,搜寻了一下,将相干的依赖包都给装置了,却还是提醒同样的问题。

# 提醒错误信息
$ docker-compose --version
error while loading shared libraries: libz.so.1: failed to map segment from shared object: Operation not permitted

解决办法:起初发现,是因为零碎中 docker 没有对 /tmp 目录的拜访权限导致,须要从新将其挂载一次,就能够解决了。

# 从新挂载
$ sudo mount /tmp -o remount,exec

4.Docker 容器文件损坏

对 dockerd 的配置有可能会影响到零碎稳固

问题起因:容器文件损坏,常常会导致容器无奈操作。失常的 docker 命令曾经无奈操控这台容器了,无奈敞开、重启、删除。刚巧,前天就须要这个的问题,次要的起因是因为从新对 docker 的默认容器进行了从新的调配限度导致的。

# 操作容器遇到相似的谬误
b'devicemapper: Error running deviceCreate (CreateSnapDeviceRaw) dm_task_run failed'

解决办法:能够通过以下操作将容器删除 / 重建。

# 1. 敞开 docker
$ sudo systemctl stop docker
# 2. 删除容器文件
$ sudo rm -rf /var/lib/docker/containers
# 3. 重新整理容器元数据
$ sudo thin_check /var/lib/docker/devicemapper/devicemapper/metadata
$ sudo thin_check --clear-needs-check-flag /var/lib/docker/devicemapper/devicemapper/metadata
# 4. 重启 docker
$ sudo systemctl start docker

5.Docker 容器优雅重启

不进行服务器下面运行的容器,重启 dockerd 服务是如许好的一件事

问题起因:默认状况下,当 Docker 守护程序终止时,它会敞开正在运行的容器。从 Docker-ce 1.12 开始,能够在配置文件中增加 live-restore 参数,以便在守护程序变得不可用时容器放弃运行。须要留神的是 Windows 平台临时还是不反对该参数的配置。

# Keep containers alive during daemon downtime
$ sudo vim /etc/docker/daemon.yaml
{"live-restore": true}
# 在守护过程停机期间放弃容器存活
$ sudo dockerd --live-restore
# 只能应用 reload 重载
# 相当于发送 SIGHUP 信号量给 dockerd 守护过程
$ sudo systemctl reload docker
# 然而对应网络的设置须要 restart 能力失效
$ sudo systemctl restart docker

解决办法:能够通过以下操作将容器删除 / 重建。

# /etc/docker/daemon.yaml
{"registry-mirrors": ["https://vec0xydj.mirror.aliyuncs.com"],  # 配置获取官网镜像的仓库地址
    "experimental": true,  # 启用试验性能
    "default-runtime": "nvidia",  # 容器的默认 OCI 运行时(默认为 runc)
    "live-restore": true,  # 重启 dockerd 服务的时候容易不终止
    "runtimes": {  # 配置容器运行时
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []}
    },
    "default-address-pools": [  # 配置容器应用的子网地址池
        {
            "scope": "local",
            "base":"172.17.0.0/12",
            "size":24
        }
    ]
}

6.Docker 容器无奈删除

找不到对应容器过程是最吓人的

问题起因:明天遇到 docker 容器无奈进行 / 终止 / 删除,认为这个容器可能又呈现了 dockerd 守护过程托管的状况,然而通过 ps -ef <container id> 无奈查到对应的运行过程。哎,起初开始开始查 supervisor 以及 Dockerfile 中的过程,都没有。这种状况的可能起因是容器启动之后,之后,主机因任何起因重新启动并且没有优雅地终止容器。剩下的文件当初阻止你从新生成旧名称的新容器,因为零碎认为旧容器依然存在。

# 删除容器
$ sudo docker rm -f f8e8c3..
Error response from daemon: Conflict, cannot remove the default name of the container

解决办法:找到 /var/lib/docker/containers/ 下的对应容器的文件夹,将其删除,而后重启一下 dockerd 即可。咱们会发现,之前无奈删除的容器没有了。

# 删除容器文件
$ sudo rm -rf /var/lib/docker/containers/f8e8c3...65720
# 重启服务
$ sudo systemctl restart docker.service

7.Docker 容器中文异样

容器存在问题话,记得优先在官网查问

问题起因:明天登陆之前部署的 MySQL 数据库查问,发现应用 SQL 语句无奈查问中文字段,即便间接输出中文都没有方法显示。

# 查看容器反对的字符集
root@b18f56aa1e15:# locale -a
C
C.UTF-8
POSIX

解决办法:Docker 部署的 MySQL 零碎应用的是 POSIX 字符集。然而 POSIX 字符集是不反对中文的,而 C.UTF-8 是反对中文的只有把零碎中的环境 LANG 改为 “C.UTF-8” 格局即可解决问题。同理,在 K8S 进入 pod 不能输出中文也可用此办法解决。

# 长期解决
docker exec -it some-mysql env LANG=C.UTF-8 /bin/bash
# 永恒解决
docker run --name some-mysql 
    -e MYSQL_ROOT_PASSWORD=my-secret-pw 
    -d mysql:tag --character-set-server=utf8mb4 
    --collation-server=utf8mb4_unicode_ci

8.Docker 容器网络互通

理解 Docker 的四种网络模型

问题起因:在本机部署 Nginx 容器想代理本机启动的 Python 后端服务程序,然而对代码服务如下的配置,后果拜访的时候始终提醒 502 谬误。

# 启动 Nginx 服务
$ docker run -d -p 80:80 $PWD:/etc/nginx nginx
nginx
server {
    ...
    location /api {proxy_pass http://localhost:8080}
    ...
}

解决办法:前面发现是因为 nginx.conf 配置文件中的 localhost 配置的有问题,因为 Nginx 是在容器中运行,所以 localhost 为容器中的 localhost,而非本机的 localhost,所以导致无法访问。

能够将 nginx.conf 中的 localhost 改为宿主机的 IP 地址,就能够解决 502 的谬误。

# 查问宿主机 IP 地址 => 172.17.0.1
$ ip addr show docker0
docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:d5:4c:f2:1e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d5ff:fe4c:f21e/64 scope link
       valid_lft forever preferred_lft forever
nginx
server {
    ...
    location /api {proxy_pass http://172.17.0.1:8080}
    ...
}

当容器应用 host 网络时,容器与宿主共用网络,这样就能在容器中拜访宿主机网络,那么容器的 localhost 就是宿主机的 localhost 了。

# 服务的启动形式有所扭转(没有映射进去端口)
# 因为自身与宿主机共用了网络,宿主机裸露端口等同于容器中裸露端口
$ docker run -d -p 80:80 --network=host $PWD:/etc/nginx nginxx

9.Docker 容器总线谬误

总线谬误看到的时候还是挺吓人了

问题起因:在 docker 容器中运行程序的时候,提醒 bus error 谬误。

# 总线报错
$ inv app.user_op --name=zhangsan
Bus error (core dumped)

解决办法:起因是在 docker 运行的时候,shm 分区设置太小导致 share memory 不够。不设置 –shm-size 参数时,docker 给容器默认调配的 shm 大小为 64M,导致程序启动时有余。

# 启动 docker 的时候加上 --shm-size 参数(单位为 b,k,m 或 g)
$ docker run -it --rm --shm-size=200m pytorch/pytorch:latest

解决办法:还有一种状况就是容器内的磁盘空间有余,也会导致 bus error 的报错,所以革除多余文件或者目录,就能够解决了。

# 磁盘空间有余
$ df -Th
Filesystem     Type     Size  Used Avail Use% Mounted on
overlay        overlay    1T    1T    0G 100% /
shm            tmpfs     64M   24K   64M   1% /dev/shm

10.Docker NFS 挂载报错

总线谬误看到的时候还是挺吓人了

问题起因:咱们将服务部署到 openshift 集群中,启动服务调用资源文件的时候,报错信息如下所示。从报错信息中,得悉是在 Python3 程序执行 read_file() 读取文件的内容,给文件加锁的时候报错了。然而奇怪的是,本地调试的时候发现服务都是能够失常运行的,文件加锁也是没问题的。起初发现,在 openshift 集群中应用的是 NFS 挂  载的共享磁盘。

# 报错信息
Traceback (most recent call last):
    ......
    File "xxx/utils/storage.py", line 34, in xxx.utils.storage.LocalStorage.read_file
OSError: [Errno 9] Bad file descriptor
# 文件加锁代码
...
    with open(self.mount(path), 'rb') as fileobj:
        fcntl.flock(fileobj, fcntl.LOCK_EX)
        data = fileobj.read()
    return data
...

解决办法:从上面的信息得悉,要在 Linux 中应用 flock() 的话,就须要降级内核版本到 2.6.11+ 才行。起初才发现,这实际上是由 RedHat 內核中的一个谬误引起的,并在 kernel-3.10.0-693.18.1.el7 版本中失去修复。所以对于 NFSv3 和 NFSv4 服务而已,就须要降级 Linux 内核版本才可能解决这个问题。

# https://t.codebug.vip/questions-930901.htm
$ In Linux kernels up to 2.6.11, flock() does not lock files over NFS (i.e.,
the scope of locks was limited to the local system). [...] Since Linux 2.6.12,
NFS clients support flock() locks by emulating them as byte-range locks on the entire file.

11.Docker 默认应用网段


启动的容器网络无奈互相通信,很是奇怪!

问题起因:咱们在应用 Docker 启动服务的时候,发现有时候服务之前能够互相连通,而有工夫启动的多个服务之前却呈现了无法访问的状况。究其原因,发现原来是因为应用的外部公有地址网段不统一导致的。有点服务启动到了 172.17 – 172.31 的网段,有的服务跑到了 192.169.0 – 192.168.224 的网段,这样导致服务启动之后呈现无法访问的状况。

解决办法:上述问题的解决形式,就是手动指定 Docker 服务的启动网段,就能够了。

# 查看 docker 容器配置
$ cat /etc/docker/daemon.json
{"registry-mirrors": ["https://vec0xydj.mirror.aliyuncs.com"],
    "default-address-pools":[{"base":"172.17.0.0/12","size":24}],
    "experimental": true,
    "default-runtime": "nvidia",
    "live-restore": true,
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []}
    }
}

12.Docker 服务启动串台


应用 docker-compose 命令各自启动两组服务,发现服务会串台!

问题起因:在两个不同名称的目录目录上面,应用 docker-compose 来启动服务,发现当 A 组服务启动结束之后,再启动 B 组服务的时候,发现 A 组当中对应的一部分服务又重新启动了一次,这就十分奇怪了!因为这个问题的存在会导致,A 组服务和 B 组服务无奈同时启动。之前还认为是工具的 Bug,起初求教了“上峰”,才晓得了起因,豁然开朗。

# 服务目录构造如下所示
A: /data1/app/docker-compose.yml
B: /data2/app/docker-compose.yml

解决办法:发现 A 和 B 两组服务会串台的起因,原来是 docker-compose 会给启动的容器加 label 标签,而后依据这些 label 标签来辨认和判断对应的容器服务是由谁启动的、谁来治理的,等等。而这里,咱们须要关注的 label 变量是 com.docker.compose.project,其对应的值是应用启动配置文件的目录的最底层子目录名称,即下面的 app 就是对应的值。咱们能够发现,A 和 B 两组服务对应的值都是 app,所以启动的时候被认为是同一个,这就呈现了上述的问题。如果须要深刻理解的话,能够去看对应源代码。

# 能够将目录结构调整为如下所示
A: /data/app1/docker-compose.yml
B: /data/app2/docker-compose.yml
A: /data1/app-old/docker-compose.yml
B: /data2/app-new/docker-compose.yml

或者应用 docker-compose 命令提供的参数 -p 来躲避该问题的产生。

# 指定我的项目项目名称
$ docker-compose -f ./docker-compose.yml -p app1 up -d

13.Docker 命令调用报错


在编写脚本的时候经常会执行 docker 相干的命令,然而须要留神应用细节!

问题起因:CI 更新环境执行了一个脚本,然而脚本执行过程中报错了,如下所示。通过对应的输入信息,能够看到提醒说正在执行的设施不是一个 tty。

随即,查看了脚本发现报错中央是执行了一个 exec 的 docker 命令,大抵如下所示。很奇怪的是,手动执行或间接调脚本的时候,怎么都是没有问题的,然而等到 CI 调用的时候怎么都是有问题。起初好好看下上面这个命令,留神到 -it 这个参数了。

# 脚本调用 docker 命令
docker exec -it <container_name> psql -Upostgres ......
咱们能够一起看下 exec 命令的这两个参数,天然就差不多了解了。-i/-interactive #即便没有附加也放弃 STDIN 关上;如果你须要执行命令则须要开启这个选项
-t/–tty #调配一个伪终端进行执行;一个连贯用户的终端与容器 stdin 和 stdout 的桥梁

解决办法:docker exec 的参数 -t 是指 Allocate a pseudo-TTY 的意思,而 CI 在执行 job 的时候并不是在 TTY 终端中执行,所以 -t 这个参数会报错。

14.Docker 定时工作异样


在 Crontab 定时工作中也存在 Docker 命令执行异样的状况!

问题起因:明天发现了一个问题,就是在备份 Mysql 数据库的时候,应用 docker 容器进行备份,而后应用 Crontab 定时工作来触发备份。然而发现备份的 MySQL 数据库竟然是空的,然而手动执行对应命令切是好的,很奇怪。

# Crontab 定时工作
0 */6 * * * 
    docker exec -it <container_name> sh -c 
        'exec mysqldump --all-databases -uroot -ppassword ......'

解决办法:起初发现是因为执行的 docker 命令多个 -i 导致的。因为 Crontab 命令执行的时候,并不是交互式的,所以须要把这个去掉才能够。总结就是,如果你须要回显的话则须要 -t 选项,如果须要交互式会话则须要 -i 选项。

-i/-interactive #即便没有附加也放弃 STDIN 关上;如果你须要执行命令则须要开启这个选项
-t/–tty  #调配一个伪终端进行执行;一个连贯用户的终端与容器 stdin 和 stdout 的桥梁

15.Docker 变量应用引号


compose 里边环境变量带不带引号的问题!

问题起因:应用过 compose 的同学可能都遇到过,咱们在编写启动配置文件的时候,增加环境变量的时候到底是应用单引号、双引号还是不应用引号。工夫长了,可能咱们总是三者是一样的,能够互相应用。然而,直到最初咱们发现坑越来越多,越来越费解。

反正我是遇到过很多是因为增加引号导致的服务启动问题,起初得出的论断就是一律不实用引号。裸奔,体验前所未有的痛快!直到现在看到了 Github 中对应的 issus 之后,才终于破案了。

# TESTVAR="test"
在 Compose 中进行援用 TESTVAR 变量,无奈找到
# TESTVAR=test
在 Compose 中进行援用 TESTVAR 变量,能够找到
# docker run -it --rm -e TESTVAR="test" test:latest
起初发现 docker 自身其实曾经正确地解决了引号的应用

解决办法:失去的论断就是,因为 Compose 解析 yaml 配置文件,发现引号也进行了解释包装。这就导致本来的 TESTVAR=”test” 被解析成了 ‘TESTVAR=”test”‘,所以咱们在援用的时候就无奈获取到对应的值。当初解决办法就是,不论是咱们间接在配置文件增加环境变量或者应用 env_file 配置文件,能不应用引号就不实用引号。

16. Docker 删除镜像报错


无奈删除镜像,归根到底还是有中央用到了!

问题起因:清理服器磁盘空间的时候,删除某个镜像的时候提醒如下信息。提醒须要强制删除,然而发现及时执行了强制删除仍旧没有成果。

# 删除镜像
$ docker rmi 3ccxxxx2e862
Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images
# 强制删除
$ dcoker rmi -f 3ccxxxx2e862
Error response from daemon: conflict: unable to delete 3ccxxxx2e862 (cannot be forced) - image has dependent child images

解决办法:起初才发现,呈现这个起因次要是因为 TAG,即存在其余镜像援用了这个镜像。这里咱们能够应用如下命令查看对应镜像文件的依赖关系,而后依据对应 TAG 来删除镜像。

# 查问依赖 - image_id 示意镜像名称
$ docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=<image_id>)
# 依据 TAG 删除镜像
$ docker rmi -f c565xxxxc87f
bash
# 删除悬空镜像
$ docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

17.Docker 普通用户切换


切换 Docker 启动用户的话,还是须要留神下权限问题的!

问题起因:咱们都晓得在 Docker 容器外面应用 root 用户的话,是不平安的,很容易呈现越权的平安问题,所以个别状况下,咱们都会应用普通用户来代替 root 进行服务的启动和治理的。明天给一个服务切换用户的时候,发现 Nginx 服务始终无奈启动,提醒如下权限问题。因为对应的配置文件也没有配置 var 相干的目录,无奈 🤷‍♀!️

# Nginx 报错信息
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2020/11/12 15:25:47 [emerg] 23#23: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

解决办法:起初发现还是 nginx.conf 配置文件,配置的有问题,须要将 Nginx 服务启动时候须要的文件都配置到一个无权限的目录,即可解决。

nginx
user  www-data;
worker_processes  1;
error_log  /data/logs/master_error.log warn;
pid        /dev/shm/nginx.pid;
events {worker_connections  1024;}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    gzip               on;
    sendfile           on;
    tcp_nopush         on;
    keepalive_timeout  65;
    client_body_temp_path  /tmp/client_body;
    fastcgi_temp_path      /tmp/fastcgi_temp;
    proxy_temp_path        /tmp/proxy_temp;
    scgi_temp_path         /tmp/scgi_temp;
    uwsgi_temp_path        /tmp/uwsgi_temp;
    include /etc/nginx/conf.d/*.conf;
}

史上最全、最具体的 Docker 学习材料  举荐给你看一看。

老手学习我的项目

举荐给大家:举荐 11 个极易上手的 Docker 实际我的项目

定期更新的 Docker 学习文章

退出移动版