docker容器

目录

什么是容器

容器是隔离的环境中运行的一个进程,如果进程结束,容器就会停止,容器的隔离环境,拥有自己的ip地址,系统文件,主机名,进程管理

程序: 代码,软件,命令

进程:正在运行的程序

容器技术出现的主要目的是为了"资源隔离"

容器技术最早出现 FreeBASE jail -----> Linux vserver

  • chroot -----> 完整的根文件系统(FHS)标准的
  • namespaces -----> UTS Mount IPC PID user network
  • cgroup -----> 资源的分配和监控

通过比较复杂的代码开发的过程,调用以上三项技术实现容器的创建 ----> 管理 ---->销毁


LXC (LinuX Container) :对于原有的常用功能进行了封装,方便我们做容器的生命周期 -----> Docker (dotcloud)

Docker是隔离环境中运行的一个进程,如果进程结束,Docker就会停止。

Docker的隔离环境,拥有自己的ip地址,系统文件,主机名,进程管理等。

容器和虚拟机的区别

bios basic input output system

虚拟机 容器
硬件cpu支持(vt虚拟化),模拟计算硬件,走正常的开机启动 不需要硬件cpu的支持,共用宿主机内核,启动容器的第一个进程
bios开机自检--根据bios启动项--读取硬盘第一个扇区grub,uefi, centos7, 加载内核,启动系统第一个进程/sbin/init systemd 容器优势: 启动快,性能高,损耗少,轻量级
100虚拟机 100个服务 10宿主机 100容器 100个服务 6宿主机

linux开机启动流程:

  • bios(basic input output system)开机自检
  • 根据bios启动项,读取硬盘第一个扇区
  • 操作系统的引导程序:grub,uefi
  • 选择启动的操作系统:centos7
  • 加载内核,硬件驱动,完成系统的初始化
  • 启动系统第一个进程:/sbin/init(centos6),systemd(centos7)

容器:共用宿主机内核,轻量级,损耗少,启动快,性能高,只能运行在linux系统上 虚拟机:需要硬件的支持,需要模拟硬件,需要走开机启动流程,可以运行不同的操作系统

image-20210306145434291

深层区别

对比项 Docker 对比结果 虚拟化
快速创建,删除 启动应用 > > 启动Guest OS+启动应用
交付,部署 容器镜像 == 虚拟机镜像
密度 单Node 100~1000 >> 但Node10~100
更新管理 迭代式更新,修改Dockerfile,对增量内容进行分发,存储,传输,节点启动和恢复迅速 >> 向虚拟机推送安装,升级应用软件补丁包
Windows支持 不支持 << 支持
稳定性 每月更新一个版本 << KVM,Xen,VMware都已很稳定
安全性 Docker具有宿主机root权限 << 硬件隔离:Guest OS运行在非跟模式
监控成熟度 还在发展过程中 << Host,Hypervisor,VM的监控工具在生产环境中已使用多年
高可用性 通过业务本身的高可用 << 武库器很丰富:快照,克隆,HA,动态迁移,异地容灾,异地双活。
管理平台成熟度 以k8s为代表,还在快速发展过程中 << 以OpenStack,vCenter,汗柏OPV-Suite为代表,已经在生产环境使用多年

image-20201121215503786

Docker安装部署

阿里云官网地址:https://mirrors.aliyun.com/docker-ce/linux/centos/

docker 0.1 ..... 1.0 ... 1.13版本

docker ce 社区版 17.03 17.06 17.09 17.12 18.03 18.06 18.09 19.03

docker ee 企业版

容器 内核3.8+

docker项目名字 moby

虚拟机 安装wordpress 运行虚拟机

docker容器 安装wordpress docker镜像

docker镜像导入 运行容器

· Docker官网:http://www.docker.com

· Docker windows入门:https://docs.docker.com/windows/

· Docker Linux 入门:https://docs.docker.com/linux/

· Docker mac 入门:https://docs.docker.com/mac/

· Docker 用户指引:https://docs.docker.com/engine/userguide/

· Docker 官方博客:http://blog.docker.com/

· Docker Hub: https://hub.docker.com/

· Docker开源: https://www.docker.com/open-source

docker主要内容

docker是一个cs架构, docker主要:镜像 容器 仓库 网络 存储 监控

docker是一个软件的打包技术.

Docker是一个开放源代码软件项目,让应用程序布署在软件货柜下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化自动管理机制

红帽官方文档:https://www.redhat.com/zh/topics/containers/whats-a-linux-container

Docker的组成:

官方文档:https://docs.docker.com/engine/dockeroverview/

Docker主机 (Host):一个物理机或虚拟机,用于运行Docker服务进程和容器。

Docker服务端 (Server): Docker 守护 进程, 运行docker容器。

Docker客户端 (Client)客户端 使用docker命令或其他工具调用docker API 。

Docker仓库 (Registry):保存镜像的仓库,类似于git或svn这样的版本控制系

Docker镜像 (Images):镜像可以理解为创建实例使用的模板。

Docker容器 (Container ): 容器是从镜像生成对外提供服务的一个或一组服务 。

Docker Hub 官方仓库:https://hub.docker.com/

Docker底层技术

  • namespaces:名称空间(内核3.8版本之后才有,centos6 内核2.6版本)

    用来隔离各个容器,可解决容器之间的冲突。

  • cgroups (Control Group):控制组

    控制程序对资源的占用,资源统计,优先级分配,进程控制。

Linux Namespace技术

namespace是Linux系统的底层概念, 在内核层实现,即有一些不同类型的命名空间被部署在核内各个``docker`容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境, 并且还可以保护 宿主机内核不受其他进 程的干扰和影响;如:文件系统空间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:

  • namespaces 名称空间
  • Control Group(cgroups) 控制组

注:为什么centos6 版本不能使用容器?

因为centos6 内核版本是2.6;容器需要一个user的名称空间,直到内核3.8版本才有:

MNT Namespace

每个容器都要有独立的根文件系统有独立的用户空间, 以实现 在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubuntu的服务器,可以在里面启动一个centos 运行环境的容器并且在容器里面启动一个Nginx服务,此 Nginx运行时使用的运行环境就是centos系统目录的运行环境 但是在容器里面是不能访问 宿主机 的资源, 宿主机是使用了 chroot 技术把容器锁定到一个指定的运行目录里面 。

IPC Namespace

一个容器内的进程间通信允许一个容器内的不同进程的内存、缓存等数据访问,但是不能夸容器访问其他容器的数据 。

UTS namespace

UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,其中包含了hostname和域名domainname,它使得一个容器拥有属于自己 hostname 标识,这个主机名标识独立于宿主机系统和其上的其他容器 。

PID Namespace

Linux系统中,有一个PID为1的进程 init/systemd是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、器内的主进程生成与回收子进程等 )。

Net Namespace

每一个容器都类似于虚拟机一样有自己的网卡、 监听 端口、TCP /IP 协议栈等。``Docker使用network namespace` 启动一个vethX接口,这样你的容器将拥有它自己的桥接ip地址,通常是docker0,而docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。

Linux control groups

在一个容器 ,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug 程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现, 宿主机有必要对容器进行资源分配 限制,比如

CPU 、内存等, Linux Cgroups 的全称是 Linux Control Groups 它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU 、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起和恢复等操作。

Docker优缺点

Docker优势: 

  • 快速部署:短时间内可以部署成百上千个应用 ,更快速交付到线上 。

  • 高效虚拟化:不需要额外的hypervisor支持,直接基于linux实现应用虚拟化,相比虚拟机大幅提高性能和效率。

  • 节省开支:提高服务器利用率,降低IT支出 。

  • 简化配置:将运行环境打包保存至容器,使用时直接启动即可。

  • 快速迁移和扩展:可跨平台运行在物理机、虚拟机、公有云等环境, 良好的兼容性可以方便将应用从A 宿主机迁移到B宿主机甚至是A平台迁移到B平台 。

Docker的缺点:

  • 隔离性:各应用之间的隔离不如虚拟机彻底 。

docker容器的核心技术:

容器规范:

  • 除了docker之外的docker技术,还有coreOS 的rkt还有阿里的 Pouch 为了保证容器生态的 标准 性和健康可持续发展, 包括 Linux 基金会 、Docker 、微软、红帽谷歌和、IBM 、等公司在2015年6月共同成立了一个叫 open container OCI的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了两个规范,分别是 runtime spec 和 image format spec ,有了这两个规范 不同 的容器 公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。

容器runtime

  • runtime是真正运行容器的地方,因此为了运行不同的容器 runtime 需要和操作系统内核紧密合作相互在 支持 ,以便为容器提供相应的运行环境 。

目前主流的三种 runtime:

Lxc:

linux上早期的runtime Docker早期就是采用lxc作为runtime 。

runc:

目前Docker 默认的 runtime runc 遵守 OCI 规范,因 此可以兼容 lxc 。

rkt:

Core OS开发的容器runtime,也符合OCI规范 ,所以使用rktruntime也可以运行Docker容器。

容器管理工具:

管理工具连接 runtime与用户,对用户提供图形或 命令方式操作,然后管理工具将用户操作传递给runtime执行 。

lxclxd的管理工具。

Runc的管理工具是 docker engine,docker engine包含后台deamoncli两部分 ,大家经常提到的Docker就是指的docker engine

Rkt 的管理工具是rktcli

容器定义工具:

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建 。

Docker image:docker容器 的模板,runtime依据docker image创建容器。

Docker file:包含N个命令的文本文件,通过``dockerfile创建出 docker image `。

ACI (App container image):docker image 类似 是 Core OS开发的``rkt`容器的镜像格式。

Linux在内核中通过namespaces,原生支持6种资源隔离,并且直接通过系统调用对外进行输出。
另外,仅靠namespaces,就可以完成容器的功能吗?
对,我们还需要靠CCgroups 控制每个namespace中的资源分配。

Linux Control Groups

用于限制一个进程组能够使用的资源上限,包括 CPU 、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起恢复等操作。

一个容器 ,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug 程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配。

cgroups 具体实现:

blkio :块设备 IO 限制。
cpu :使用调度程序为 cgroup 任务提供 cpu 的访问。
cpuacct :产生 cgroup 任务的 cpu 资源报告。
cpuset :如果是多核心的 cpu ,这个子系统会为 cgroup 任务分配单独的 cpu 和内存。
devices :允许或拒绝 cgroup 任务对设备的访问。
freezer :暂停和恢复 cgroup 任务。
memory :设置每个 cgroup 的内存限制以及产生内存资源报告。
net_cls :标记每个网络包以供 cgroup 方便使用。
ns :命名空间子系统。
perf_event :增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的 group 的所有线程以及运行在特定 CPU 上的线程。

docker-ce的安装

主机名 内存 ip
docker01 2G 10.0.0.11
docker02 2G 10.0.0.12

安装docker-ce

wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
mkdir docker1903_rpm
find /var/cache/yum -type f -name  "*.rpm" |xargs mv -t docker1903_rpm
scp -rp docker1903_rpm  root@10.0.0.12
yum  makecache  fast               
yum install docker-ce -y

启动Docker

systemctl enable docker
systemctl start docker

验证

[root@docker01 yum.repos.d]# docker version 
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:25:41 2019
 OS/Arch:           linux/amd64
 Experimental:      false
docker  info

docker镜像

镜像搜索

docker search nginx

优先选择:OFFICIAL(官方),STARS 数量多的镜像。安全

不带版本号默认 latest,也就是最新版本


镜像拉取(下载)

docker pull nginx:alpine

注意版本选择,版本请到Docker Hub查看

docker pull nginx:1.18-alpine

国内镜像源

官方镜像 docker.io/library/nginx:1.18-alpine
用户镜像 docker.io/t29617342/alpine:3.9
国内镜像 index.tenxcloud.com/system_containers/metrics-server-amd64:v0.3.1

镜像推送(上传)

docker push 镜像名

默认上传至官方仓库,需要先登录

docker login

配置镜像加速

阿里云Docker-hub
https://cr.console.aliyun.com/cn-hangzhou/mirrors

注: #由于国外网速比较慢,特此配置国内网址让其快速拉取镜像

多种加速方式:

法一:

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://uoggbpok.mirror.aliyuncs.com"]
}
EOF

systemctl daemon-reload
systemctl restart docker

法二:

vim   /etc/docker/daemon.json
	{
		 "registry-mirrors": ["https://68rmyzg7.mirror.aliyuncs.com"]
	}	
systemctl daemon-reload
systemctl restart docker

Docker体系结构

image-20201121215012045

image-20201121215042718

注:Docker镜像没有内核

由于容器启动和运行过程中是直接使用宿主机的内核,所以没有直接调用过物理硬件所以也不会涉及到硬件驱动, 因此也用不上内核和驱动,另外有内核的那是虚拟机

查询镜像

docker image ls
docker image  ls -q 
docker inspect ID/name:tag
[root@docker /]# docker image inspect ubuntu:latest
[root@docker /]# docker image inspect 82f3b5f3c58f  
docker search   搜索镜像, 优先选官方,stars数量多
查看docker详细信息
docker info    

参数解释:

REPOSITORY        # 镜像所属的仓库名称
TAG               # 镜像版本号(标识符) 默认为 latest
IMAGE ID          # 镜像唯一ID标示
CREATED           # 镜像创建时间
VIRTUAL SIZE      #  镜像的大小

标识镜像唯一性的方法

REPOSITORY:TAG
centos:7.5.1804 
IMAGE ID (sha256:64位的号码,默认只截取12位)
82f3b5f3c58    
[root@docker /]# docker image ls --no-trunc 

创建并启动容器

time docker  run -d  -p 80:80  nginx:alpine 
time docker  run -d  -p 80:80  nginx:1.18-alpine
run 创建并启动一个容器
-d  放后台启动
-p  端口映射
nginx:alpine docker镜像名称
-it    分配一个交互式的终端
docker run -it centos:7  启动并进入容器

删除镜像

docker rmi nginx:alpine
docker image rm 98ab35023fd6

镜像标签

docker tag         
docker  tag  d3689906a86  oldboy:v1

查看镜像列表

docker image  ls  
docker image inspect oldboy:v1

清理无效镜像

docker image  import  docker_nginx_alpine.tar.gz
docker image prune 
[root@docker02 ~]#  for n in `ls *.tar.gz`;do docker image load -i $n;done  
[root@docker02 ~]#  wget http://192.168.15.253/docker_images/ && wget -i index.html -F -B http://192.168.15.253/docker_images/ && ls *.gz |xargs -i docker load -i {} && docker images
-i,  --input-file=FILE     下载本地或外部 FILE 中的 URLs。
-F,  --force-html   把输入文件当成 HTML 文件。
-B,  --base=URL            解析与 URL 相关的
HTML 输入文件(由 -i -F 选项指定)。

推送镜像(上传镜像)

docker push 

导入镜像

docker load    
①docker image load -i docker_nginx_alpine.tar.gz
②docker load < docker_nginx_alpine.tar.gz

导出镜像

docker save    
docker image save  nginx:alpine -o docker_nginx_alpine.tar.gz 

注:

  • -o:指定导出镜像的位置;
  • 可以同时导出多个镜像;为一个文件;
  • 指定.tar.gz 可以导出并压缩。

自动构建镜像

docker build --network=host -t REPOSITORY:TAG .
--network=host  # 指定构建时使用宿主机的hosts文件
-t              # 指定仓库:标签

注意:容器每次启动都会挂载新生成的/etc/host文件


查看镜像构建历史

docker history nginx:latest

查看镜像或容器信息

docker inspect nginx:v1
docker inspect 98ab35023fd6
docker inspect -f "{{.NetworkSettings.IPAddress}}" f625e984b18d # 查看容器IP
docker inspect -f "{{.NetworkSettings.Gateway}}" f625e984b18d   # 查看容器网关
docker inspect -f "{{.State.Pid}}" f625e984b18d                 # 查看容器PID号
docker inspect -f "{{.HostConfig.NetworkMode}}" f625e984b18d    # 查看容器网络模式
docker inspect f625e984b18d | grep IPAddress
docker inspect f625e984b18d | grep Gateway
docker inspect f625e984b18d | grep Pid
docker inspect f625e984b18d | grep NetworkMode
docker inspect f625e984b18d | grep -A 1 Networks

nsenter

  • 安装 nsenter
yum install util-linux -y
  • 查看容器PID号
docker inspect -f "{{.State.Pid}}" f625e984b18d
  • nsenter 进入容器
nsenter -t 容器PID -m -u -i -n -p  # 根据容器PID号进入到容器中
  • 脚本:进入容器(k8s中常用)
# vim docker_in.sh
# usage: docker_in.sh CONTAINERID
#    ie: docker_in.sh 14fa729e9d46
#!/bin/bash
docker_in(){
   NAME_ID=$1
   PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})
   nsenter -t ${PID} -m -u -i -n -p
  }
docker_in $1

docker容器的常用命令

run  创建并启动容器
-t :打开一个终端,像使用交换机一样使用容器
-i:交互式访问
--name:容器名字
--network:指定网络
--rm:容器一停,自动删除
-d:剥离与当前终端的关系;否则会一直占据着终端
-p:端口映射,将容器内服务的端口映射在宿主机的指定端口
-p <container port>
-p <hostport>:<container port>
-p <hostip>:<hostport>:<container port>
--dns 223.5.5.5    # 指定容器dns
-i                 # 交互式访问
-t                 # 分配一个交换式的终端,和-d同用放后台
-e                 # 设置环境变量
--privileged=true  # 授予此容器扩展权限,可以修改内核参数
--restart always   # docker服务启动时启动容器
--link             # 单向链接正在运行的容器,hosts文件中添加主机名/别名解析
-h                 # 指定容器的主机名
--memory 50M       # 限制内存

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

docker container stats --no-stream
#查看各个已启动容器的使用内存情况  可以通过杀死进程
 docker run -d --memory 10M kod:v4  #限制启动时的内存
docker system df #查看所有容器镜像使用情况
docker volume prune 清除卷的信息
docker container update --memory 4M 485f51b3ba80  更新容器的内存

注:容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!

创建并启动容器

docker  run 
docker  run  === docker  container create +  docker container start
docker run  -d -it -p 80:80  nginx:latest
[root@docker02 ~]# docker run -d -it --name oldboy nginx:alpine
[root@docker02 ~]# docker run -it centos:7
#退出容器 
[root@40dbc2bdd61b ~]# exit
docker run -d -i -t <imageID> /bin/bash 

报错Failed to get D-Bus connection: Operation not permitted

注:容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会秒退!

docker run -d -i -t <imageID> /usr/sbin/init

创建容器

docker create    --name id号

启动容器

Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]

  • -a:附加到当前终端
  • -i:交互式
docker start
docker contain start centos:7
 docker start `docker ps -a -q`  #开启所有容器

停止容器

docker  stop 
docker contain stop  centos:7
docker stop `docker ps -a -q`  #停止所有容器

重启容器

docker  restart 
docker contain restart centos:7

强制停止容器

docker  kill 
docker  container kill oldgirl
docker  kill `docker ps -a -q`批量强制停止docker所有容器

查看容器列表

docker  ps 
docker container ps -a
docker container ls -a  # -a 查看所有容器列表,默认只显示运行的容器
docker ps -q                # -q 只显示IMAGE ID(sha256:64位的号码,默认只截取12位)
docker ps --no-trunc        # 不截断IMAGE ID输出
docker ps -f status=exited  # 查看退出的状态的容器
docker ps -l                # 查看最后创建的容器

重名名容器

docker rename oldboy oldboy01

删除容器

docker  rm         
docker container rm centos:7
docker rm -fv `docker ps -aq -f status=exited` #批量删除已经退出状态的容器

显示所有容器的ID号码

[root@docker02 ~]# docker container ps -a -q
40dbc2bdd61b  

批量删除所有容器

 docker rm -f `docker ps -a -q`

显示最后一个容器

[root@docker02 ~]# docker ps -l -a  

清除停止容器

docker container prune

进入正在运行的容器

docker exec -it 容器id/容器名字 /bin/sh(/bin/bash)  # 分配一个新终端
docker exec -it centos:7 ls                        # 免交互执行命令
docker attach centos:7   # 使用同一个终端,将后台运行的终端调用到前台

容器想要放在后台一直运行,那么容器的初始命令,必须夯住(前台运行),否则容器就会退出.

nginx -g 'daemon off;'  # 指定全局选项:关闭守护进程,在前台运行
/usr/sbin/php-fpm --nodaemonize # 在前台运行
  • 退出容器:exit
  • 偷偷离开容器,容器不退出:ctrl+q,p

查看容器进程

docker top d9e3ab321e18

更新容器选项

docker update --restart always 6d0a073d0b50
docker update --memory 50M --memory-swap 50M

提交容器为镜像

docker commit 6d0a073d0b50 test:v2

快捷键ctrl +p +q 离开容器快捷键,并没有退出容器。

容器想要放在后台一直运行的,那么容器的初始命令,必须夯住(前台运行),否则容器就会退出.

前台运行
nginx -g 'daemon off;'
/usr/sbin/php-fpm --nodaemonize
docker container logs
[root@docker02 ~]# docker run -d  centos:7 tail -F /etc/hosts
[root@docker02 ~]# docker run -d -it --name web centos:7     

指定容器的DNS

[root@docker01 yum.repos.d]# docker run -it --dns 223.5.5.5 centos:7 bash       #指定容器的阿里云的dns地址
[root@e5a721eee1df /]# cat /etc/resolv.conf  
nameserver 223.5.5.5
[root@e5a721eee1df /]# ping 223.5.5.5   #ping通dns地址

查看容器日志

docker logs d9e3ab321e18
-t       # 显示时间戳
-f       # 跟踪日志输出
--tail N # 仅列出最新N条容器日志

注意:

ln -s /dev/stdout /var/log/nginx/access.log

导出容器到归档文件镜像:

没有名字、标签及构建历史,所有层合并为一层,只能用import导入。

docker export 6d0a073d0b50 > docker_test.tar.gz

比较容器不同

docker diff 6d0a073d0b50

挂起容器

docker pause 6d0a073d0b50

取消挂起容器

docker unpause 6d0a073d0b50

统计容器资源

docker stats --no-stream
--no-stream # 不动,不刷新

查看容器内部的hosts文件

[root@docker01 yum.repos.d]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.15.253  mirrors.aliyun.com
172.17.0.1 92f05acd794b
[root@docker01 yum.repos.d]# ping 92f05acd794b

docker端口映射

docker port 容器ID/容器名 查看容器端口映射

image-20201130212356001

-p <container port> 容器端口
-p <hostport>:<container port>宿主机端口:容器端口
-p <hostip>:<hostport>:<container port>
# docker run -it alpine:3.9 
-p  宿主机端口:容器端口
# docker run -d  -p 10.0.0.9:80:80 nginx:alpine   
-p  宿主机ip1:宿主机端口:容器端口 (多个容器同时使用80端口)
docker run -d  -p 10.0.0.9:80:80 nginx:alpine
# docker run -d -p 81:80 --name oldliu 26cf1ed9b144
-p  宿主机ip1::容器端口   随机端口映射
docker run -d 10.0.0.11::80 nginx:alpine    
-p  宿主机ip1::容器端口/udp   使用udp协议做随机端口映射
# docker run -d -p 10.0.0.11::80/udp -p 10.0.0.11::/tcp nginx:alpine
-p 80:80  -p 3306:3306  
#docker run -d -p 81:80 -p 3306:3306 nginx:alpine    
-p 1111-1119:1111-1119  端口范围映射
# docker run -d -p 91-99:81-89 nginx:alpine    
-P 自动随机端口映射  
# docker run -d -P nginx:alpine 
映射宿主机随机端口到容器指定端口
# docker container run -d -p 80 --name='n5' nginx:1.14

docker数据卷

目前 Docker的数据类型分为两种, 一 是数据卷,二是数据容器 ,数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上。

数据卷容器最大的功能是可以让数据在多个docker容器之间共享,即可以让B容器访问A容器的内容,而容器C也可以访问A容器的内容,即先要创建一个后台运行的容器作为Server,用于提供这个卷,可以为其他容器提供数据存储服务其他使用此卷的容器作为client端。

数据卷的特点及使用:

1、数据卷是目录或者文件,并且可以在多个容器之间共同使用 。

2、对数据卷更改数据容器里面,会立即更新 。

3、数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不 影响 。

4、 在容器里面的写入数据,不会影响到镜像本身

数据卷使用场景:

1、 日志输出

2、 静态web页面

3、应用配置文件

4、 多容器间目录或文件共享

image-20201130230204441

docker run
-v  宿主机绝对目录:容器目录
-v  容器目录        #创建一个随机卷,来持久化容器的目录下的数据   数据卷
-v  卷名:容器目录    #创建一个固定名字的卷,来持久化容器的目录下的数据
# ls
containerd  yiliao  yiliao.tar.gz
# docker run -d -p 80:80 -v /opt//yiliao:/usr/share/nginx/html nginx:alpine
# docker container cp yiliao bf05ce2cf511:/opt  #将医疗网站挂载到容器/opt目录下
docker run -v /opt alpine:3.9    将容器的/opt目录持久化
docker run -v opt:/opt alpine:3.9 将opt卷挂载到容器的/opt
# docker exec -it bf05ce2cf511 /bin/bash
docker run -d /etc:/tmp -v /usr/bin:/opt -v /tmp:/data centos:7
--volumes-from  跟某一个容器挂载所有相同的卷
# docker volume ls  #查看卷的数据
删除所有的容器,不影响卷的数据
# docker run -it --volumes-from e3429eb0a534 nginx:alpine

可用于代码上线 nginx 静态资源共享等,类似于NFS,可以实现容器间数据共享。

在当前环境下,即使把提供卷的容器Server删除,已经运行的容器 Client依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器Server创建后即可正,创建卷容器Client,
此方式可以用于线上数据库 、共享数据目录等环境因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用。

数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于 NFS 共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性。

复制文件

在容器和本地文件系统之间复制文件/文件夹

docker cp [OPTIONS] 容器:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- 容器:DEST_PATH

查看卷列表

docker volume ls

卷存储在:/var/lib/docker/volume

案例:

只启动一个nginx容器,要求访问80端口,出现nginx默认欢迎首页,访问81端口,出现小鸟飞飞.

[root@docker01 ~]#yum install nginx -y
[root@docker01 ~]#systemctl start nginx    
[root@docker01 ~]# mkdir /code/
[root@docker01 ~]# cd /code/
[root@docker01 code]# wget http://192.168.15.253/xiaoniaofeifei.zip
cat >>/etc/nginx/conf.d/local.conf <<EOF
server {
listen   81;
server_name  localhost;
location / {
root   /code;
 index  index.html index.htm;
}
}
EOF
[root@docker01 code]#systemctl restart nginx
[root@docker01 code]# docker run -d -p 80:80 -p 81:81 -v /code:/code -v  /etc/nginx/conf.d/local.conf:/etc/nginx/conf.d/local.conf nginx:latest
[root@docker01 code]# docker ps -l -a
CONTAINER ID        IMAGE               COMMAND                  CREATED         STATUS              PORTS                      NAMES
ac9db852cce8        nginx:latest        "nginx -g 'daemon of…"   9 seconds ago   Up 8 seconds        0.0.0.0:80-81->80-81/tcp   flamboyant_clarke

方法1:
docker run -d -p 80:80 -p 81:81 -v /opt/xiaoniao:/code  nginx:latest   
docker  exec -it id号   /bin/bash
cd /etc/nginx/conf.d/
echo '
  server {
listen   81;
server_name  localhost;
location / {
root   /code;
 index  index.html index.htm;
}
}  ' >xiaoniao.conf
exit
docker restart id号
docker ps -a  -l   
方法2:
docker run -d -p 82:80 -p 83:81 -v /opt/xiaoniao:/code  nginx:latest
docker cp xiaoniao.conf id号:/etc/nginx/conf.d
docker restart id号
docker ps -a  -l   
方法3:
docker run -d -p 84:80 -p 85:81 -v /opt/xiaoniao.conf:/etc/nginx/conf.d/xiaoniao.conf -v /opt/xiaoniao:/code nginx:latest
docker ps -a  -l    

docker system

docker system df     # 统计docker-ce使用磁盘空间
docker system prune  # 清理停止的容器,未使用的网卡,无名的镜像和构建缓存
docker system info   # 查看docker-ce信息
docker system even   # 查看docker-ce事件

关闭docker服务,不关闭容器

cat > /etc/docker/daemon.json <<EOF
{
  "live-restore": true
}
EOF

Docker服务进程

查看docker进程,了解docker的运行及工作方式

[root@docker01 ~]# pstree -p
systemd(1)─┬─VGAuthService(816)
           ├─abrt-watch-log(837)
           ├─abrtd(832)
           ├─agetty(848)
           ├─auditd(759)───{auditd}(760)
           ├─containerd(1390)─┬─containerd-shim(2053)─┬─bash(2069)
           │                  │                       ├─{containerd-shim}(2054)
           │                  │                       ├─{containerd-shim}(2055)
           │                  │                       ├─{containerd-shim}(2056)
           │                  │                       ├─{containerd-shim}(2057)
           │                  │                       ├─{containerd-shim}(2058)
           │                  │                       ├─{containerd-shim}(2059)
           │                  │                       ├─{containerd-shim}(2061)
           │                  │                       └─{containerd-shim}(2087)
           │                  ├─{containerd}(1424)
           │                  ├─{containerd}(1425)
           │                  ├─{containerd}(1426)
           │                  ├─{containerd}(1433)
           │                  ├─{containerd}(1434)
           │                  ├─{containerd}(1448)
           │                  ├─{containerd}(1452)
           │                  ├─{containerd}(1946)
           │                  └─{containerd}(1949)
           ├─crond(841)
           ├─dbus-daemon(820)
           ├─dockerd(1451)─┬─{dockerd}(1519)
           │               ├─{dockerd}(1520)
           │               ├─{dockerd}(1521)
           │               ├─{dockerd}(1533)
           │               ├─{dockerd}(1537)
           │               ├─{dockerd}(1538)
           │               ├─{dockerd}(1543)
           │               ├─{dockerd}(1559)
           │               └─{dockerd}(1969)

containerd进程关系

四个进程:

  • containerd:被dockerd进程调用以实现与runc交互,其父进程为宿主机的systemd守护进程 。
  • dockerd:被client直接访问,其父进程为宿主机的systemd守护进程 。
  • containerd-shim:真正运行容器的载体,其父进程为containerd。
  • docker-proxy:实现容器通信,其父进程为dockerd。

手动制作docker镜像

制作一个基于centos7系统的nginx镜像(单服务)

法一:

[root@docker01 ~]# docker run -it -p 80:80  centos:7
 echo "192.168.15.253  mirrors.aliyun.com" >>/etc/hosts
 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
 curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install nginx -y
 ps -ef
rm -rf /usr/share/nginx/html/index.html
echo 'web01' > /usr/share/nginx/html/index.html
[root@docker01 ~]# exit 
[root@docker01 ~]# docker container commit 4da1ea044061 centos7_nginx:v1
[root@docker01 ~]# docker ps -a -l
[root@docker01 ~]# docker run -d -p 81:80 centos7_nginx:v1 nginx -g 'daemon off;'
[root@docker01 ~]# docker ps -a -l
[root@docker01 ~]# curl -I 10.0.0.11:81

浏览器访问10.0.0.11:81查看

法二:

[root@docker01 ~]# docker run -it -p 80:80  centos:7
 echo "192.168.15.253  mirrors.aliyun.com" >>/etc/hosts
 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
 curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install nginx -y
 ps -ef
rm -rf /usr/share/nginx/html/index.html
echo 'web01' > /usr/share/nginx/html/index.html
[root@docker01 ~]# exit 
[root@docker01 ~]# docker container commit 4da1ea044061 centos7_nginx:v1
[root@docker01 ~]# docker run -d -p 82:80 centos7_nginx:v1 tail -f /etc/hosts
[root@docker01 ~]# docker exec -it 778ad62dca6 /bin/bash
[root@778ad62dca6f /]# nginx -t
[root@778ad62dca6f /]# nginx
[root@docker01 ~]# docker ps -a -l
[root@docker01 ~]# curl -I 10.0.0.11:82

重新访问浏览器10.0.0.11:82窗口

制作一个支持ssh登录的镜像

[root@docker01 ~]# docker run -it -p 1022:22 centos:7
echo "192.168.15.253  mirrors.aliyun.com" >>/etc/hosts
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@docker01 /]# which sshd
/usr/sbin/sshd
[root@docker01 /]# rpm -qf /usr/sbin/sshd
openssh-server-7.4p1-16.el7.x86_64
[root@docker01 /]# cat /usr/lib/systemd/system/sshd.service
[root@d73226869185 /]#yum install openssh-server -y
[root@docker01 ~]#rpm -qf /etc/rc.d/init.d/functions
[root@d73226869185 /]#yum install  initscripts -y
[root@d73226869185 /]#/usr/sbin/sshd-keygen
[root@d73226869185 /]#echo '123456'|passwd --stdin root
[root@d73226869185 /]#/usr/sbin/sshd
 ctrl+p,q
[root@docker01 ~]#ssh 10.0.0.11:1022
[root@docker01 ~]#docker commit id号 centos7_sshd:v1
[root@docker01 ~]#docker run -d -p 1023:22 centos7_sshd:v1 /usr/sbin/sshd -D
[root@docker01 ~]#docker ps -al
 ssh 10.0.0.11 -p1023

制作一个支持ssh登录的nginx镜像

启动centos7_sshd安装nginx

启动centos7_nginx安装sshd

  1. 启动一个纯净的centos:7容器并进入*
docker run -it -p 100:22 -p 80:80 centos:7
  1. nginx sshd initscripts 安装 启动
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install nginx initscripts openssh-server -y
/usr/sbin/sshd-keygen
rm -rf /usr/share/nginx/html/index.html
echo "nginx" > /usr/share/nginx/html/index.html
cat > init.sh <<-EOF
#!/bin/bash

chmod +x init.sh
exit

  1. 把安装好服务的容器,提交为镜像
docker commit 32364fd2b78f centos7_nginx_sshd:v1
  1. 测试镜像的功能
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns centos7_nginx_sshd:v1 /init.sh
docker top cns
curl -I 10.0.0.11
docker ps -al
rm -rf .ssh/known_hosts
ssh 10.0.0.11 -p100

手动制作centos7系统的kod网盘的镜像(多服务)

思路:启动一个centos7_nginx:v1,再安装php

docker run -it -p 80:80 centos7_nginx:v1 /bin/bash
cat > init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
/usr/sbin/php-fpm -D
nginx -g 'daemon off;'
EOF
chmod +x init.sh
mkdir /code && cd /code
curl -o /code/kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip
echo "192.168.15.253 mirrors.aliyun.com" >> /etc/hosts
yum install php-fpm php-gd php-mbstring unzip -y
unzip -d /code/html kodexplorer4.40.zip
chown -R nginx:nginx /code
sed -i 's/= apache/= nginx/g' /etc/php-fpm.d/www.conf
sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
cat > /etc/nginx/conf.d/kod.conf <<-EOF
server {
    listen 80;
    server_name kod.oldboy.com;
    root /code/html;
    index index.php index.html;
    client_max_body_size 100m;

    location / {
    }
         
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
        include        fastcgi_params;
    }
}
EOF
exit

提交检测镜像

docker stop `docker ps -lq`
docker commit `docker ps -lq` kod:v1

docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns kod:v1 /init.sh
docker ps -al --no -trunc

浏览器访问:10.0.0.11:81

基于centos7系统的LNMP架构wordpress镜像(多服务)

  1. 启动一个纯净的centos:7容器并进入
docker run -it -p 100:22 -p 80:80 centos:7
wget -O http://192.168.15.253/docker_images/wordpress-latest.tar.gz /opt/dockerfile/wordpress
docker cp /opt/dockerfile/wordpress/wordpress-latest.tar.gz `docker ps -lq`:/root
  1. 安装
cat > init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
/usr/libexec/mariadb-prepare-db-dir
/usr/bin/mysqld_safe --basedir=/usr &
/opt/remi/php72/root/usr/sbin/php-fpm -D
nginx
sleep 2
mysql -e 'CREATE DATABASE wordpress;GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost" IDENTIFIED BY "1";FLUSH PRIVILEGES;'
/usr/sbin/sshd -D
EOF
chmod +x init.sh

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm

yum install nginx initscripts openssh-server php72-php-fpm php72-php-mysqlnd mariadb-server -y && yum clean all && rm -rf /var/cache/yum/*

/usr/sbin/sshd-keygen && mkdir /code && cd /code

mv /root/latest-zh_CN.tar.gz .

tar xf wordpress-latest.tar.gz   && chown -R nginx:nginx /code && sed -i 's/= apache/= nginx/g' /etc/opt/remi/php72/php-fpm.d/www.conf && sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf

cat > /etc/nginx/conf.d/wordpress.conf <<-EOF
server {
    listen 80;
    server_name wordpress.oldboy.com;
    root /code/wordpress;
    index index.php index.html;
    client_max_body_size 100m;

    location / {
    }
         
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
        include        fastcgi_params;
    }
}
EOF

exit
  1. 把安装好服务的容器,提交为镜像
docker stop `docker ps -lq`
docker commit `docker ps -lq` lnmp_wp:v1
  1. 测试镜像的功能
docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" lnmp_wp:v1 /init.sh

自动制作docker镜像

自动构建镜像思路

  1. 手动制作docker镜像,记录历史命令

  2. 根据历史命令编写dockerfile文件

  3. docker build构建docker镜像

    docker build --network=host -t REPOSITORY:TAG .
    

    docker build 基于dockerfile制作镜像的命令

    ① 格式:

    docker build [OPTIONS] PATH | URL | -
    

    ② 选项:

    • -t:打标签
    • -c,- cpu-shares int :CPU份额(相对权重)
    • -m,- memory bytes:内存限制
    • --build-arg:设置构建时变量,就是构建的时候修改ARG指令的参数

    4.测试镜像的功能

FROM

基础镜像

  • FROM 指令必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM语句;
  • FROM 指令用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像所提供的运行环境;
  • 实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会自动从Docker 的公共库pull 镜像下来。如果找不到指定的镜像文件,docker build 会返回一个错误信息;
  • FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
  • 如果FROM语句没有指定镜像标签,则默认使用latest标签。

格式

FROM <repository>[:<tag>] 或
FROM <repository>@<digest>

注:

<repository>:指定作为base image的名称;
<tag>:base image的标签,省略时默认latest;
<digest>:是镜像的哈希码;使用哈希码会更安全一点;

示例

# Description: test image
FROM busybox:latest

RUN

制作镜像过程中需要的执行命令(安装服务)

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/bash", "-c", "<executable>", "<param1>"]

CMD

容器启动的时候执行的初始命令,容易被替换(启动服务)

类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同

RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像文件启动一个容器时

CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,*CMD指定的命令其可以被docker run的命令行选项所覆盖,而ENTRYPOINT不会被后面的docker run 命令覆盖。

在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效

语法:

CMD <command>  或
CMD [“<executable>",“<param1>","<param2>"]  或
CMD ["<param1>","<param2>"]

注:

  • 前两种语法格式的意义同RUN
  • 第三种则用于为ENTRYPOINT指令提供默认参数
  • json数组中,要使用双引号,单引号会出错

ENTRYPOINT

容器启动的时候执行的初始命令,不能被替换,如果同时使用CMD和ENTRYPOINT,cmd命令将作为ENTRYPOINT命令的参数

类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序

与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序

不过,docker run命令的 --entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序

语法

ENTR YPOINT <command>
ENTRYPOINT ["<executable>", "<param1>", "<param2>"]

注:docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用

Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效

HEALTHCHECK

HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。

即使服务器进程仍在运行,这也可以检测出陷入无限循环且无法处理新连接的Web服务器等情况。

语法

HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令来检查容器运行状况)
HEALTHCHECK NONE (禁用从基础映像继承的任何运行状况检查)

OPTIONS 选项:

--interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒

-- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒

--start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒

--retries=N (default: 3):认为检测失败几次为宕机,默认3次

(2)返回值:

0:容器成功是健康的,随时可以使用

1:不健康的容器无法正常工作

2:保留不使用此退出代码

示例

(1)编写dockerfile文件

FROM busybox
LABEL maintainer="Along <along@along.com>" app="httpd"
ENV WEB_DOC_ROOT="/data/web/html"
RUN mkdir -p ${WEB_DOC_ROOT} && \
echo "<h1>Busybox httpd server</h1>" > ${WEB_DOC_ROOT}/index.html
CMD /bin/httpd -f -h ${WEB_DOC_ROOT}
HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:10080/

ONBUILD

用于在Dockerfile中定义一个触发器

Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件

在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令**定义的触发器

语法

ONBUILD < Instruction>

尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令

使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuil

在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败

ADD

介绍

把dockerfile当前目录下的文件拷贝到容器中(自动解压tar包)

ADD 指令类似于COPY指令,ADD支持使用TAR文件和URL路径

格式

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>;

COPY 网上路径(URL)的tar包

编写dockerfile文件

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/src/

注:ADD 的 是网上的nginx下载路径

vim etc/os-release
wget  https://mirror.tuna.tsinghua.edu.cn/lxc-images/images/alpine/3.12/amd64/default/20201130_13%3A00/rootfs.tar.xz
tar zcf ../oldboy.tar.gz *
cd ..
rm -rf rootfs
cat dockerfile
FROM scratch
ADD oldboy.tar.gz /
CMD ["/bin/sh"]
docker build -t alpine_oldboy:v1 .
docker run -it alpine_oldboy:v1                                               

COPY

COPY 用于从docker 主机复制新文件或者目录至创建的新镜像指定路径中 (不解压tar包)

格式

COPY <src>... <dest>  或
COPY ["<src>",... "<dest>"]

注::要复制的源文件或目录,支持使用通配符

:目标路径,即正在创建的image的文件系统路径;建议使用绝对路径,否则,COPY指定以WORKDIR为其实路径

在路径中有空白字符时,通常使用第2中格式;

文件复制准则

<src>必须是build上下文中的路径,不能是其父目录中的文件;
如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制;
如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾;
如果<dest>事先不存在,他将会被自动创建,这包括父目录路径。

示例

COPY 文件

编写dockerfile文件

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/    #要确保dockerfile 同级路径下有index.html文件

在dockerfile同级目录下准备好index.html文件

$ vim index.html
<h1>Busybox httpd server</h1>

使用build 制作镜像

$ docker build -t busyboxhttpd:v0.1 ./
Sending build context to Docker daemon 3.072 kB
Step 1/3 : FROM busybox:latest
 ---> 758ec7f3a1ee
Step 2/3 : MAINTAINER "Along <along@along.com>"
 ---> Running in 0d6f4c1c0e8d
 ---> 5d2cda1631d7
Removing intermediate container 0d6f4c1c0e8d
Step 3/3 : COPY index.html /data/web/html/
 ---> 2e0fe0eb0cb7
Removing intermediate container 536fdc71472a
Successfully built 2e0fe0eb0cb7

基于此新建镜像运行容器,进行验证

[root@along ~]# docker run --name web1 --rm busyboxhttpd:v0.1 cat /data/web/html/index.html
<h1>Busybox httpd server</h1> 

注:--rm:在容器关闭时,直接删除容器,方便实验。

COPY 目录

编写dockerfile文件

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/

注:如果是复制目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制;需要把复制目录名字也写在容器中要复制的路径下!

dockerfile同级目录下准备yum.repos.d 目录

[root@along img1]# cp -r /etc/yum.repos.d/ ./
[root@along img1]# ls yum.repos.d
along.repo  docker-ce.repo  epel-release-latest-7.noarch.rpm  epel.repo  epel-testing.repo

使用build 制作镜像,其中-t选项是打一个标签

[root@along img1]# docker build -t busyboxhttpd:v0.2 ./
Sending build context to Docker daemon 27.65 kB
Step 1/4 : FROM busybox:latest
 ---> 758ec7f3a1ee
Step 2/4 : MAINTAINER "Along <along@along.com>"
 ---> Using cache
 ---> 5d2cda1631d7
Step 3/4 : COPY index.html /data/web/html/
 ---> Using cache
 ---> 2e0fe0eb0cb7
Step 4/4 : COPY yum.repos.d /etc/yum.repos.d/
 ---> 68586925bdf9
Removing intermediate container a01f824efa3e
Successfully built 68586925bdf9

基于此新建镜像运行容器,进行验证

[root@along ~]# docker run --name web1 --rm busyboxhttpd:v0.2 ls /etc/yum.repos.d/
along.repo
docker-ce.repo
epel-release-latest-7.noarch.rpm
epel-testing.repo
epel.repo

WORKDIR

指定容器的默认工作目录

WORKDIR /root  指定目录为/root

用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录

格式

WORKDIR <dirpath>

在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径;

另外,WORKDIR也可调用由ENV指定定义的变量;

示例

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
WORKDIR /usr/local/
ADD nginx-1.15.8.tar.gz ./src/

EXPOSE

镜像要暴露的端口,用于为容器打开指定要监听的端口以实现与外部通信

语法

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ....

注:

 <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
-  EXPOSE指令可一次指定多个端口,例如:EXPOSE 11211/udp 11211/tcp

示例

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/src/
WORKDIR /usr/local/
ADD nginx-1.15.8.tar.gz ./src/ 
VOLUME /data/mysql 
EXPOSE 80/tcp

注:就算dockerfile 中有EXPOSE 指令暴露端口,但是不是真正的暴露;需要在启动容器时,使用-P 选项真正的暴露端口。**

VOLUME

持久化卷:用于在image中创建一个挂载点目录,以挂载Docker host.上的卷或其它容器上的卷

语法

VOLUME <mountpoint>  或
VOLUME ["<mountpoint>"]

注:如果挂载点目录路径下此前在文件中存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中

示例

编写dockerfile文件
# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/ 
#ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/src/
WORKDIR /usr/local/
ADD nginx-1.15.8.tar.gz ./src/
VOLUME /data/mysql  # 挂载到/data/mysql目录下

ENV

​ 环境变量(ssh的密码,数据库的密码)

  • 用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用
  • 调用格式为$variable_ name 或 $

格式

ENV <key> <value>  或
ENV <key>=<value> . .

注:

第一种格式**中,<key>之后的所有内容均会被视作其<value>的组成部分, 因此,一次只能设置一个变量;
第二种格式可用一次设置多个变量,每个变量为一个”<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线(\)进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行;
定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"
ENV DOC_ROOT=/data/web/html/ \
WEB_SERVER_PACKAGE="nginx-1.15.8" 
COPY index.html ${DOC_ROOT}
COPY yum.repos.d /etc/yum.repos.d/
#ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/src/
WORKDIR /usr/local/
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/ 
VOLUME /data/mysql
EXPOSE 8080:80/tcp

示例

法一:

mkdir centos7_sshd/
cd centos7_sshd/
cat  dockerfile
FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install openssh-server initscripts -y
RUN /usr/sbin/sshd-keygen
COPY init.sh /init.sh 
CMD ["/bin/bash","/init.sh"]
vi init.sh
#!/bin/bash
echo "$SSH_PASS"|passwd --stdin root  
nginx 
/usr/sbin/sshd -D 
docker build --network=host -t centos7_sshd:v1 .
docker run -d -p 2022:22 -e "SSH_PASS=123" centos7_sshd:v1
ssh root@10.0.0.11 -p2022 

法二:

mkdir centos7_sshd/
cd centos7_sshd/
cat  dockerfile
FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install openssh-server initscripts -y
RUN /usr/sbin/sshd-keygen
ENV SSH_PASS 456
COPY init.sh /init.sh 
CMD ["/bin/bash","/init.sh"]
vi init.sh
#!/bin/bash
echo "$SSH_PASS"|passwd --stdin root  
nginx 
/usr/sbin/sshd -D 
docker build --network=host -t centos7_sshd:v2 .
docker run -d -p 2023:22  centos7_sshd:v2
ssh root@10.0.0.11 -p2023

LABEL

​ 镜像的属性标签

MAINTAINER

管理者标识

用于让dockerfile制作者提供本人的详细信息

dockerfile 并不限制MAINTAINER 指令可在出现的位置,但推荐将其放置于FROM指令之后

格式

MAINTAINER <authtor's detail>

示例

# Description: test image
FROM busybox:latest
MAINTAINER "Along <along@along.com>"

不常用的 dockerfile 指令

USER

介绍

用于指定运行image时的或运行Dockerfile中任何RUN、CMD或EntRyPoInT指令指定的程序时的用户名或UID

默认情况下,container的运行身份为root用户

格式

USER <UID>| <U JserName >
需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/ passwd中某用户的有效UID,否则,docker run命令将运行失败

ARG

介绍

ARG指令类似ENV,定义了一个变量;区别于ENV:用户可以在构建时docker build --build-arg = 进行对变量的修改;ENV不可以;

如果用户指定了未在Dockerfile中定义的构建参数,那么构建输出警告

格式

ARG <name>[= <default value>]

Dockerfile可以包含一个或多个ARG指令

示例

(1)在dockerfile 中定义ARG

FROM busybox:latest
ARG author="Along <along@along.com>"
MAINTAINER $ARG

(2)构建此时镜像时,修改此age

docker build --build-arg author="Tom <tom@tom.com>" -t test:v0.1 .

SHELL

介绍

SHELL指令允许覆盖用于shell命令形式的默认shell。

Linux上的默认shell是[“/ bin / sh”,“c”],在Windows上是[“cmd”,“/ S”,“/ C”]

SHELL指令必须以JSON格式写入Dockerfile。

语法

SHELL ["executable", "parameters"]

SHELL指令可以多次出现。

每个SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令。

STOPSIGNAL

介绍

STOPSIGNAL指令设置将发送到容器出口的系统调用信号。

此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或者SIGNAME格式的信号名,例如SIGKILL

语法

STOPSIGNAL signal

dockerfile单服务实战nginx

cd /opt
mkdir dockerfile/
cd dockerfile/
mkdir centos7_nginx
cd centos7_nginx/
vim dockerfile 
FROM centos:7
RUN echo "192.168.15.253  mirrors.aliyun.com" >>/etc/hosts
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install nginx -y
RUN rm -rf /usr/share/nginx/html/index.html
RUN echo 'web01' > /usr/share/nginx/html/index.html
CMD ["nginx","-g","daemon off;"]
docker image build  --network=host  -t centos7_nginx:v2  .
[root@docker01 centos7_nginx]# docker run -d -p 82:80 centos7_nginx:v2
curl -I 10.0.0.11:82   #查看响应状态
curl  10.0.0.11:82     #查看输出结果

docker ps -al --no-trunc  #查看全称命令
docker run -d --restart always  #重启不会死掉     
docker container update --restart always 6d0a073d0b50 #更新容器

dockerfile多服务实战: NGINX+PHP

FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install nginx -y
RUN rm -rf /usr/share/nginx/html/index.html
RUN echo 'web01' > /usr/share/nginx/html/index.html
RUN yum install php-fpm php-gd php-mbstring -y
ADD www.conf /etc/php-fpm.d/www.conf
ADD kod.conf 
RUN sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
/etc/nginx/conf.d/kod.conf 
RUN mkdir /code 
WORKDIR /code
RUN 
RUN curl -o /code/kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip
RUN yum install unzip -y
RUN unzip kodexplorer4.40.zip 
RUN chown -R nginx:nginx /code
RUN sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
ADD init.sh   /init.sh
EXPOSE 80
VOLUME  /code
CMD ["/bin/bash","/init.sh"]
vi /init.sh
#!/bin/bash
php-fpm -D
nginx -g 'daemon off;'
[root@docker01 dockerfile]# docker images kod
docker cp id号:/etc/nginx/conf.d/kod.conf .
docker cp id号:/etc/php-fpm.d/www.conf .
docker build --network=host -t kod:v1 .
docker rm -f `docker ps -a -q`
docker run -d -p 81:80 kod:v4

浏览器访问:10.0.0.11:81

dockerfile的wordpress镜像

MySQL镜像

docker run -it -p 100:22 -p 80:80 centos:7
mkdir -p /opt/dockerfile/wordpress/
cd /opt/dockerfile/wordpress
wget http://mirrors.aliyun.com/repo/Centos-7.repo  http://mirrors.aliyun.com/repo/epel-7.repo https://cn.wordpress.org/latest-zh_CN.tar.gz
cat > /opt/dockerfile/wordpress/repo/MariaDB.repo <<EOF
[mariadb]
name=MariaDB
baseurl=https://mirrors.ustc.edu.cn/mariadb/yum/10.5/centos7-amd64/
gpgcheck=0
enabled=1
EOF
cat > /opt/dockerfile/lnmp_wordpress/repo/wordpress.conf <<-EOF
server {
    listen 80;
    server_name wordpress.oldboy.com;
    root /code/wordpress;
    index index.php index.html;
    client_max_body_size 100m;

    location / {
    }
         
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
        include        fastcgi_params;
    }
}
EOF
cat > /opt/dockerfile/wordpress/init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
/usr/libexec/mariadb-prepare-db-dir
/usr/bin/mysqld_safe --basedir=/usr &
/opt/remi/php72/root/usr/sbin/php-fpm -D
nginx
sleep 2
mysql -e 'CREATE DATABASE wordpress;GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost" IDENTIFIED BY "1";FLUSH PRIVILEGES;'
/usr/sbin/sshd -D
EOF
cat > /opt/dockerfile/wordpress/Dockerfile <<EOF
FROM centos:7
COPY repo /etc/yum.repos.d/
RUN yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm && \
yum install nginx initscripts openssh-server php72-php-fpm php72-php-mysqlnd mariadb-server -y && \
yum clean all && \
rm -rf /var/cache/yum/* && \
/usr/sbin/sshd-keygen && \
mkdir /code && cd /code && \
mv /etc/yum.repos.d/latest-zh_CN.tar.gz . && \
tar xf latest-zh_CN.tar.gz && \
rm -f latest-zh_CN.tar.gz && \
chown -R nginx:nginx /code && \
sed -i 's/= apache/= nginx/g' /etc/opt/remi/php72/php-fpm.d/www.conf && \
sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf && \
mv /etc/yum.repos.d/wordpress.conf /etc/nginx/conf.d/wordpress.conf && \
mv /etc/yum.repos.d/init.sh /init.sh && \
chmod +x init.sh
CMD ["/init.sh"]
EOF
docker build -t lnmp_wp:v1 /opt/dockerfile/lnmp_wordpress/
docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns lnmp_wp:v1 /init.sh

Docker镜像的分层

Dokcer镜像含有启动容器所需要的文件系统及其内容,用于创建并启动docker容器。


Dokcer镜像采用分层构建机制,最底层为Bootfs,之上为rootfs,再额外挂载"可写"层。

  • bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载,以节约内存资源;

  • rootfs:位于bootfs之上,表现为docker容器的根文件系统;由内核挂载为“只读”模式

  • "可写"层:通过UnionFS(联合文件系统)额外挂载的一个"可写"层;

    "可写"层之间通过parent文件中存放的父层sha256关联。

    [root@docker01 ~]# tree /var/lib/docker/image/
    /var/lib/docker/image/
    `-- overlay2  # 存储驱动
        |-- distribution
        |-- imagedb  # 镜像文件
        |   |-- content
        |   |   `-- sha256
        |   |       `-- aa88f087d1bcf434df7494c64931fec52782e8aa4041959bc51ee9d6bd5cdc49
        |   `-- metadata
        |       `-- sha256
        |           |-- 7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd
        |           |   `-- parent # 父sha256
        |           `-- fdb81b0740bdb34e37846eb4ded59fd1a243db356d2d309ccd51e9b0a75ad56f
        |               `-- parent
        |-- layerdb
        |   |-- mounts
        |   |   `-- d1c6a7f266126296b12ddc79ef8d26ccadd4a43f15b7f54f635239ecbdf9b09d
        |   |       |-- init-id
        |   |       |-- mount-id
        |   |       `-- parent
        |   |-- sha256
        |   |   |-- d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854
        |   |   |   |-- cache-id
        |   |   |   |-- diff
        |   |   |   |-- size
        |   |   |   `-- tar-split.json.gz
        |   |   `-- fe986c7da4b1268db8eccd9cce00f27565eb3c574d6353e8d4309c2cc68fa27d
        |   |       |-- cache-id
        |   |       |-- diff    # 相对于父层的不同
        |   |       |-- parent  # 父层sha256
        |   |       |-- size
        |   |       `-- tar-split.json.gz
        |   `-- tmp
        `-- repositories.json
    
    [root@docker01 ~]# cat /var/lib/docker/image/overlay2/layerdb/sha256/fe986c7da4b1268db8eccd9cce00f27565eb3c574d6353e8d4309c2cc68fa27d/parent
    sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854
    
    [root@docker01 ~]# cat /var/lib/docker/image/overlay2/imagedb/metadata/sha256/fdb81b0740bdb34e37846eb4ded59fd1a243db356d2d309ccd51e9b0a75ad56f/parent 
    sha256:7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd
    
    [root@docker01 ~]# cat /var/lib/docker/image/overlay2/imagedb/metadata/sha256/7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd/parent
    sha256:aa88f087d1bcf434df7494c64931fec52782e8aa4041959bc51ee9d6bd5cdc49
    

docker image layer

  • 位于下层的镜像成为父镜像,最底层的成为基础镜像
  • 最上层为可读写层,其下的均为只读层;

image-20210306145223324

image-20210306145152304

[root@docker01 ~]# docker save centos7_nginx:v1 -o docker_centos7_nginx.tar.gz
[root@docker01 ~]# scp -p  docker_centos7_nginx.tar.gz  root@10.0.0.12:/root 
[root@docker02 ~]# docker load -i docker_centos7_nginx.tar.gz
716e85a193d1: Loading layer  210.8MB/210.8MB       #分层    
/var/lib/docker/overlay2  #存储镜像文件
rootfs (root file system) 包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。
runtime 是容器真正运行地方

镜像构建过程

新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

Docker镜像的分层实现了资源共享,节省占用空间。

Docker存储驱动

  1. Docker默认存储驱动为overlay2需要磁盘分区支持d_type文件分层功能 ,因此需要系统磁盘的额外支持。官方文档 /var/lib/docker/overlay2

  2. Docker官方推荐首选存储驱动为overlay2,其次为devicemapper。但是devicemapper存在使用空间方面的一些限制, 虽然可以通过后期配置解决,但是官方依然推荐使用overlay2。

注意:

  • 如果docker数据目录是一块单独的xfs格式的磁盘分区,那么需要在格式化时加上参数 -n ftype=1,否则后期在启动容器的时候会报错不支持d_type

    centos7.2 版本后默认 ftype=1

    [root@docker01 ~]# xfs_info /
    meta-data=/dev/mapper/centos-root isize=512    agcount=4, agsize=1232128 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=0 spinodes=0
    data     =                       bsize=4096   blocks=4928512, imaxpct=25
             =                       sunit=0      swidth=0 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal               bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=0 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    

dockerfile的优化

优化原则:构建的镜像尽可能小,构建速度尽可能快;

  1. 使用小体积镜像:(体积最小)alpine > debian > ubuntu > centos

  2. 尽量减少中间图层(仅RUN,COPY和ADD指令创建图层)

    FROM ubuntu:18.04
    COPY . /app
    RUN make /app
    CMD python /app/app.py
    
  3. 利用构建缓存:修改dockerfile时,尽可能把修改的内容放在最后

  4. 使用.dockerignore文件,构建docker镜像时,排除当前目录下不需要的文件

    cat > .dockerignore <<-EOF
    filename
    EOF
    

alpine:3.9 nginx 的优化

docker tag alpine:3.9 lph
docker run -it -p 84:80 lph
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories  #替换
apk add nginx 
mkdir /run/nginx/
echo 'lph' > /html/index.html;
vi /etc/nginx/nginx.conf
 nginx -s reload
docker commit 0345d5599040 alpine_nginx:v1
docker images|grep nginx

linux操作系统的区别 包管理工具 配置文件路径 (部分)例如网卡内核版本,编译器

centos: yum httpd apache软件 lrzsz 软件

debian/Ubuntu: apt-get /etc/int nginx apache2软件 rzsz 软件

alpine apk

centos :编译器 gcc glibc jdk.rpm jdk.tar.gz

alpine 编译器 musl libc

alpine debine/ubuntu centos

优化kod云

[root@docker01 kod]# cat dockerfile
FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && \
 yum install nginx -y && \
yum install php-fpm php-gd php-mbstring unzip -y && \
rm -fr /var/cache/yum/*
ADD www.conf /etc/php-fpm.d/www.conf
ADD kod.conf /etc/nginx/conf.d/kod.conf 
RUN mkdir /code 
WORKDIR /code
RUN curl -o /code/kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip && \
 unzip kodexplorer4.40.zip && \
 chown -R nginx:nginx /code
ADD init.sh   /init.sh
EXPOSE 80
VOLUME  /code
CMD ["/bin/bash","/init.sh"]
[root@docker01 kod]# docker build --network=host -t kod:v4 .

容器间的互联

docker run --link 正在运行容器的名字(单方向)

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问 ,比如一个业务前端静态页面是使用nginx,动态页面使用的是tomcat由于容器在启动的时候其内部IP地址是DHCP随机分配的,所以如果通过内部访问的话,自定义名称是相对比较固定的,因此比较适用于此场景。

定义别名:

上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦, 因此可以使用自定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可,具体如下:

命令格式:

docker run -d -name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell 命令

docker一键部署zabbix

① rz 上传包
② wget http://192.168.15.253/docker_images/docker-mysql-5.7.tar.gz
wget http://192.168.15.253/docker_images/zabbix-web-nginx-mysql.tar.gz
wget http://192.168.15.253/docker_images/zabbix-server-mysql.tar.gz
wget http://192.168.15.253/docker_images/zabbix-java-gateway.tar.gz


for n in `ls *.tar.gz`;do docker image load -i $n;done 
docker run --name mysql-server -it \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -d mysql:5.7 \
      --character-set-server=utf8 --collation-server=utf8_bin

docker run --name zabbix-java-gateway -t \
      -d zabbix/zabbix-java-gateway:latest
    
docker run --name zabbix-server-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
      --link mysql-server:mysql \
      --link zabbix-java-gateway:zabbix-java-gateway \
      -p 10051:10051 \
      -d zabbix/zabbix-server-mysql:latest
      

docker run --name zabbix-web-nginx-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      --link mysql-server:mysql \
      --link zabbix-server-mysql:zabbix-server \
      -p 80:80 \
      -d zabbix/zabbix-web-nginx-mysql:latest

浏览器访问:10.0.0.11 ZABBIX

docker一键部署wordpress

 docker run --name mysql-wp -it \
      -e MYSQL_DATABASE="blog" \
      -e MYSQL_USER="blog" \
      -e MYSQL_PASSWORD="blog" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -d mysql:5.7 \
      --character-set-server=utf8 --collation-server=utf8_bin
	  
docker run --name wordpress  -p 81:80 --link mysql-wp:mysql -e WORDPRESS_DB_HOST=mysql \
    -e WORDPRESS_DB_USER=blog -e WORDPRESS_DB_PASSWORD=blog -d wordpress:latest

浏览器访问:10.0.0.11:81 wordpress

docker-compose单机版的容器编排

Compose是一个用于定义和运行多容器Docker应用程序的工具。使用Compose,您可以使用Compose文件来配置应用程序的服务。然后,使用单个命令,您可以从配置中创建并启动所有服务。

Compose非常适合开发,测试和登台环境以及CI工作流程。

(1)使用Compose基本上是一个三步过程

  1. 定义您的应用程序环境 Dockerfile,以便可以在任何地方进行复制。
  2. 定义构成应用程序的服务 docker-compose.yml,以便它们可以在隔离环境中一起运行。
  3. 最后,运行docker-compose up,Compose将启动并运行整个应用程序。

(2)docker-compose.yml 示例: Compose文件参考

version: '3'
  
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: redis

(3)Compose具有管理应用程序整个生命周期的命令:

  • 启动,停止和重建服务
  • 查看正在运行的服务的状态
  • 流式传输运行服务的日志输出
  • 在服务上运行一次性命令

(4)Docker Compose 升级

  如果从Compose 1.2或更早版本升级,请在升级Compose后删除或迁移现有容器。因为从1.3版本开始,Compose使用Docker标签来跟踪容器,并且需要重新创建容器以添加标签。

  如果Compose检测到没有标签创建的容器,它将拒绝运行,您最终不会使用两组。如果要继续使用现有容器(例如,因为它们具有要保留的数据卷),可以使用Compose 1.5.x使用以下命令迁移它们:

docker-compose migrate-to-labels

或者,如果您不担心保留它们,可以将它们删除。撰写只是创建新的。

docker container rm -f -v myapp_web_1 myapp_db_1 ...

安装

  • Docker Compose 依靠 Docker Engine 工作。

  要以非root用户身份运行Compose,请参阅以非root用户身份管理Docker

  • yum安装依赖epel源
yum install docker-compose -y
docker-compose:批量管理一组容器

批量创建并启动

docker-compose up -d
-d # 后台启动

以目录分隔组,只读取当前目录下的 docker-compose.yml、docker-compose.yaml 文件

停止并删除一组容器

docker-compose down

批量启动

docker-compose start 

批量停止

docker-compose stop

批量重启

docker-compose restart 

指定批量规模

docker-compose scale

zabbix容器批量部署yml

vim vim docker-compase.yml
version: '3'

services:
   mysql-server:
     image: mysql:5.7
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: root_pwd
       MYSQL_DATABASE: zabbix
       MYSQL_USER: zabbix
       MYSQL_PASSWORD: zabbix_pwd
     command: --character-set-server=utf8 --collation-server=utf8_bin
     
   zabbix-java-gateway:
     image: zabbix/zabbix-java-gateway:latest
     restart: always
     
   zabbix-server:
     depends_on:
       - mysql-server
     image: zabbix/zabbix-server-mysql:latest
     restart: always
     environment:
       DB_SERVER_HOST: mysql-server
       MYSQL_DATABASE: zabbix
       MYSQL_USER: zabbix
       MYSQL_PASSWORD: zabbix_pwd
       MYSQL_ROOT_PASSWORD: root_pwd
       ZBX_JAVAGATEWAY: zabbix-java-gateway
     ports:
       - "10051:10051"
       
   zabbix-web-nginx-mysql:
     depends_on:
       - zabbix-server
     image: zabbix/zabbix-web-nginx-mysql:latest
     ports:
       - "80:80"
     restart: always
     environment:
       DB_SERVER_HOST: mysql-server
       MYSQL_DATABASE: zabbix
       MYSQL_USER: zabbix
       MYSQL_PASSWORD: zabbix_pwd
       MYSQL_ROOT_PASSWORD: root_pwd

启动服务

docker-compose  up  -d    

停止服务

docker-compose  down   

启动多个命名不同的容器

docker-compose scale --h
$ docker-compose scale web=2 worker=3
docker-compose scale zabbix-java-gateway:latest  zabbix-java-gateway_1

wordpress容器批量部署yml

cp -a zabbix wordpress 
cd wordpress
cat  docker-compose.yml 
version: '3'

services:
   mysql:
     image: mysql:5.7
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: root_pwd
       MYSQL_DATABASE: wordpress
       MYSQL_USER: blog
       MYSQL_PASSWORD: blog
     command: --character-set-server=utf8 --collation-server=utf8_bin
     
     
   wordpress:
     depends_on:
       - mysql
     image: wordpress:latest
     ports:
       - "83:80"
     restart: always
     environment:
       WORDPRESS_SERVER_HOST: mysql
       WORDPRESS_DB_USER: blog
       WORDPRESS_DB_PASSWORD: blog 

[root@docker01 wordpress]# docker-compose up -d
[root@docker01 wordpress]# docker ps
posted @ 2021-03-06 14:56  上善若水~小辉  阅读(353)  评论(0编辑  收藏  举报