Docker

容器概念

容器是一种基础的工具;泛指任何可以用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳,存储,运输物品;物体可以被放置在容器中,而容器则可以保护内容物;
人类使用容器的历史至少有十万年,甚至可能有数百万年的历史
容器的类型
瓶 —— 指口部比腹部窄小,颈长的容器.
罐 —— 指那些开控较大,一般为近圆筒形的器皿.
箱 —— 通常是立方体或圆柱体.形状固定.
篮 —— 以条状物编织而成.
桶 —— 一种圆柱形的器皿
袋 —— 柔性材料制成额容器,形状会受内容物而变化
瓮 —— 通常是指陶制,口小肚大的容器
碗 —— 用来盛载食品的容器
柜 —— 指一个由盒组成的家具
鞘 —— 用于装载刀刃的容器

------------- LXC(Linux容器 Docker是LXC的增强版) 虚拟化 --------------
主机级虚拟化: (作用:环境隔离)
Type-I
Type-II

Linux Namespace
namespace 系统调用参数 隔离内容 内核版本
UTS CLONE_NEWUTS 主机名和域名 2.6.19
IPC CLONE_NEWIPC 信号量,消息队列和共享内存 2.6.19
PID CLONE_NEWPID 进程编号 2.6.24
Network CLONE_BEWNET 网络设备,网络线,端口等 2.6.29
Mount CLONE_NEWNS 挂载点(文件系统) 2.4.19
USer CLONE_NEWUSER 用户和用户组 3.8

-------------------- Cgroups --------------
Control Group(cgroups)
资源控制组,是Linux内核提供的一种可以限制,记录,隔离进程组(process groups)所使用的物理资源(如 cpu memory i/o 等等)的机制,2007年进入Linux2.6.24的内核,Cgroups不是全新创造的,它将进程管理从cpuset中剥离出来

cgroups
blkio: 块设备IO
cpu: CPU
cpuacct: CPU资源使用报告
cpuset: 多处理器平台上的CPU集合
devices: 设备访问
freezer: 挂起或恢复任务
memory: 内存用量及报告
perf_event: 对cgroup中的任务进行统一性能测试
net_cls: cgroup中的任务创建的数据报文的类别标识符

Cgroup四大功能:
资源限制: 可以对任务使用的资源总额进行限制
优先级分配: 通过分配的CPU时间片数量以及磁盘IO带宽大小,实际上相当于控制了任务运行优先级
资源统计: 可以统计系统的资源使用量,如CPU时长,内存用量等
任务控制: Cgroup可以对任务执行挂起,恢复等操作


OCF
Open Container Format

OCI
Open Container Initiative
由Linux基金会主导与2015年6月创立
旨在围绕容器格式和运行时指定一个开放的工业化标准
contains two specifications
the Runtime Specifications # 运行标准
the Image Specifications # 镜像标准

======================= Docker =======================

Docker解决的问题

  • 环境不一致
  • 多版本测试

Docker VS 虚拟机

类型 Docker 虚拟机
部署难度 非常简单 组件多,部署复杂
启动速度 秒级别 分钟级
执行能力 与物理系统几乎一致 VM会占用一些资源
镜像体积 镜像体积是MB级别 镜像体积是GB级别
管理效率 建立简单 组件相互依赖,管理复杂
隔离性 隔离性高 彻底隔离
客观理性 单进程 完整的系统管理
网络连接 比较弱 借助Neutron可以灵活组件各类网络架构

Docker下载
linux:
1.安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

2.设置阿里云镜像源

sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

3.安装 Docker-CE
重建 Yum 缓存。
安装 Docker-CE ,请执行一下命令进行安装:

sudo yum install docker-ce

Linux Docker配置文件地址
/etc/docker/daemon.json

4.启动 Docker-CE
sudo systemctl enable docker
sudo systemctl start docker

5.[可选] 为 Docker 建立用户组#
docker 命令与 Docker 引擎通讯之间通过 UnixSocket ,但是能够有权限访问 UnixSocket 的用户只有 root 和 docker 用户组的用户才能够进行访问,所以我们需要建立一个 docker 用户组,并且将需要访问 docker 的用户添加到这一个用户组当中来。

  1. 建立 Docker 用户组

sudo groupadd docker

2.添加当前用户到 docker 组

sudo usermod -aG docker $USER
sudo systemctl enable docker
sudo systemctl start docker

6.镜像加速配置#

这里使用的是 阿里云提供的镜像加速 ,登录并且设置密码之后在左侧的 Docker Hub 镜像站点 可以找到专属加速器地址,复制下来。
阿里云镜像加速官网
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

然后执行以下命令:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'


{
"registry-mirrors": ["你的加速器地址"],
"dns":["192.168.56.2","223.5.5.5"], # 选填 增加dns解析
"bip": xxx.xx.x.xx, # 选填 更改docker 自己的网络桥地址
"hosts": ["tcp://ip:端口","unix:///var/run/docker/sock"], # 选填 跟修改vi /usr/lib/systemd/system/docker.service 中的 ExecStart 一致
"data-root":"/data/docker"	# 选填 指定存放docker下载文件以及其他存储地址 默认在/var/lib/docker/
"cluster-store":"consul://启动consul的设备ip:端口", # 选填 多台设备集群参数
"cluster-advertise":"本机ip:2375" # 必须配置下面远程控制的参数 vi /usr/lib/systemd/system/docker.service 
}

EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

如果需要远程控制
vi /usr/lib/systemd/system/docker.service
修改
ExecStart=/usr/bin/dockerd -H tcp://ip -H unix:///var/run/docker.sock # -H unix:///var/run/docker.sock 是本地访问 必须要加

之后重新加载配置,并且重启 Docker 服务
systemctl daemon-reload
systemctl restart docker

Mac:
https://yeasy.gitbooks.io/docker_practice/content/install/mac.html

$ brew cask install docker

手动下载:
https://download.docker.com/mac/stable/Docker.dmg
https://download.docker.com/mac/edge/Docker.dmg

镜像加速配置 访问阿里查看详细demo
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

右键点击桌面顶栏的 docker 图标,选择 Preferences ,在 Daemon 标签(Docker 17.03 之前版本为 Advanced 标签)下的 Registry mirrors 列表中将

https://mk3q07hr.mirror.aliyuncs.com加到"registry-mirrors"的数组里,点击 Apply & Restart按钮,等待Docker重启并应用配置的镜像加速器。

Docker 命令

补充:
在容器中使用exit会关闭容器(docker默认机制,当容器没有进程,会关闭容器)
需要在不关闭容器的同时退出 在键盘按住 control 先按 "p" 再按 "q"


docker version	# 查看客户端以及服务端的版本

docker info # 详细docker信息 # Containers 容器数量 # Running 运行数量 # Paused 暂停状态 # Stopped 停止状态 # Images 镜像数量 # Server Version 服务器版本 # Storage Driver 存储驱动后端 # Plugins 插件 # Volume 存储插件 # Network网络插件 # Log 日志插件 # Security Options 安全选项  # Kernel Version 内核版本 # Registry Mirrors 加速镜像

docker search	关键字	# 搜索镜像

docker inspect 容器name # 检查容器信息
-f {{.xxx}} # 根据go模板语法进行层级查询 # .可以理解/

docker rmi 镜像id	# 删除镜像

images

docker pull xxx # 拉取镜像
busybox (杂物箱)

docker images # 查看所有镜像

docker rm	xxx # 删除容器
-f # 强制删除 例如删除正在运行的容器

docker history xxx # 查询镜像层级

Management Commands

docker network ls	# 查看网络
# bridge 桥接 # 默认
# host # 网卡信息与速度与宿主机是一样的

docker network create name # 新建网络
--driver 网络模式	# 必须加 可以不写网络模式 默认是桥接
--subnet xxx.xxx.xxx.xxx # 指定网段
--geteway xxx.xxx.xxx.xxx # 指定网关
-d 驱动name	# 指定驱动
-d overlay # 如果使用这个 创建一个全局的网卡 overlay网络模式
# 使用同一个用户创建的网络建立容器是可以互相ping通的

docker network connect 网络端 容器name # 将某网卡放入容器中 可以实现在同一网段的容器间的通讯

commands


docker commit 容器name/ID [仓库名/镜像名:版本]
-m 添加一些注释信息
-p 容器name # 创建新镜像
-c 'CMD ["/bin/httpd","-f"]'	# 修改容器起始命令 'CMD ["/bin/httpd","-f"]' 命令格式
docker -H ip:端口 指令 # 指定ip执行某指令

docker create xxx # 创建容器

docker start xxx	# 启动一个或多个处于停止状态的容器
-l # 交互模式
# 或者使用 docker attach xxx 连接进入shell # 如果多端连入会同步一个屏幕操作
# 或使用 docker exec -it xxx bash/sh # 在容器中 # 多端连接不会出现attach现象

docker stop xxx # 停止一个或多个处于运行状态的容器

docker kill	xxx	# 强制停止运行状态的容器

docker run 指令 指定镜像 起始命令	# 直接创建完直接启动 如果没有起始命令则会执行默认的起始命令
-t	# 交互式接口 打开shell
-l # 允许交互
--name xxx	# 起名 也可以直接ping xxx 跨容器通讯
--network # 指定网络
# 默认是bridge 如果需要指定其他 
# overlay 集群网络
-h name # 指定主机名 # 在镜像中输入hostname查看
--dns xxx # 指定dns解析地址
--rm # 容器停止自动删除
-d	# 运行在后台
-e # -e 后跟指令变量 用于携带参数 类似ansible的-e
-m # -m后跟内存 例如50M 细粒度控制
--memory-swap # 必须先设置 -m 参数后才能使用这个参数 例如 -m 正数M --memory-swap 正数S 容器的可用总空间为S,其中ram(物理内存)为M,swap(交换内存)为(S-M),若S=M则无可swap空间 // -m 正数M --memory-swap 0 相当未设置swap(unset) 若主机启用(docer host)swap则容器可用swap为2*M // -m 正数M --memory-swap -1 若主机启用(docer host)swap则容器可使用最大至主机上的所有swap空间的swap资源

--omm-kill-disable # 禁止omm被kill掉
--cpuset-cpus num # 指定cpu执行 num也可以指定范围 1-3 表示1-3核
-c	num # 指定cpu权重 如果不指定默认为1024 按照权重分配CPU 
--cpus=<value> # 指定cpu核数 例如 --cpus="1.5" 使用1.5核
--link 容器name:别名 # 链接容器name 可以通过ping别名来ping被链接的容器ip
--ip xxx.xxx.xxx.x # 指定ip
-v path # 将容器中的 path目录随机绑定到本机上 需要使用docker inspect 容器name 查看"Mounts" 中随机分配的路径 两者路径互通
-v path1:path # 将本地文件path1挂载到path
--volumes-from 容器name # 复制容器name的卷 创建新容器

docker pause	xxx	# 暂停容器

docker unpause xxx # 取消暂停

docker top # 查看运行的容器详情 (根据资源消耗排名)

docker ls # 列出所有容器 等于 docker ps
-a # 为查看所有的容器,包括已经停止的。

docker logs -f <容器名 or ID> # 查看容器日志

docker exec 容器名 指令 # 在容器内运行外部的指令 # 指令必须为绝对指令 例如 /bin/sh
-t	# 交互式接口 打开shell
-l # 交互模式
-e # -e后加入指令

docker save 镜像name # 可以支持多镜像打包
-o 绝对地址/文件name # 将打包的镜像导出到文件

docker load -i 打包的镜像文件 # 将压缩包的镜像容器导入

docker container ls -a 查看运行容器
- f 增加条件检索 例如 $docker container ls -f "status=exited" 状态为停止的


# 一共有三种形式进行端口映射
docker -p ip:hostPort:containerPort # 映射指定地址的主机端口到容器端口
# 例如:docker -p 127.0.0.1:3306:3306 映射本机3306端口到容器的3306端口
docker -p ip::containerPort # 映射指定地址的任意可用端口到容器端口
# 例如:docker -p 127.0.0.1::3306 映射本机的随机可用端口到容器3306端口
docer -p hostPort:containerPort # 映射本机的指定端口到容器的指定端口
# 例如:docker -p 3306:3306 # 映射本机的3306端口到容器的3306端口

docker port 容器ip/name # 查看容器中映射内容

映射数据卷

docker -v /home/data:/opt/data # 这里/home/data 指的是宿主机的目录地址,后者则是容器的目录地址

Tag
-alpine # docker pull xxx:版本-alpine 构建小镜像版本

command
bash
sh

容器container

1.创建容器
docker create -it boke-oraclexe:1.0

# 创建临时容器,退出后不再存在,常用于排错

docker run -it --rm boke-mysql5.5:1.1 bash

2.查看容器
docker ps -a

docker ps -a -q # 查看哪些是停止状态的容器

3.启动容器
docker start 容器ID


4.创建启动容器
docker run

# 当使用docker run命令创建启动容器时,Docker在后台运行的标准操作有下面几个步骤

# 1、检测本地是否存在指定的镜像,不存在就从公有仓库下载

# 2、利用镜像创建并启动一个容器

# 3、分配一个文件系统,并在只读的镜像层外面挂载一层可读写层

# 4、从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去

# 5、从地址池配置一个IP地址给容器

# 6、执行用户指定的应用程序

# 7、执行完毕后终止容器


5.停止容器

# 运行中的容器status 为 up

# 停止中的容器status 为exit

docker stop 容器ID


6.进入容器
几种方式 1.docker attach 命令、2.docker exec 命令、3.nsenter工具
6.1.attach命令
docker attach 容器ID

docker attach是一个Docker自带的命令,下面来说说attach命令的使用方法:

其实使用docker attach命令有时候很不方便,当多个窗口同时attach到同一个容器的时候,所有窗口都会同步显示,当某个窗口因命令阻塞的时候,其他窗口也无法执行操作了。


6.2.exec命令
在Docker1.3版本开始,提供了一个更方便的命令exec。可以直接在容器内运行命令。


7.删除容器
删除容器我们可以使用docker rm命令,被删除的容器需要是终止状态的

命令用法:docker rm [OPTIONS] CONTAINER [CONTINER...]。支持的参数有-f -l -v

-f, --force=false:强项终止并删除一个运行中的容器。

-l, --link=false:删除容器的连接,但保留容器。

-v, --volumes=false:删除容器挂载的数据卷。


8.容器迁移

导出 docker export 容器ID

导入docker import 容器ID

 

### 登录到官方仓库 并将镜像提交至官方仓库
docker login
user:songzhibin
password:xxxxxxxx

docker tag 镜像id 你的用户名/镜像名:版本号 # 版本号不输入默认是latest

docker push 已经打好的tag

GUI 管理配置

这里推荐使用 Portainer 作为容器的 GUI 管理方案。

官方地址:https://portainer.io/install.html

安装命令:

docker volume create portainer_data
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
访问你的 IP:9000 即可进入容器管理页面。

===============单级容器的编排

docker-compose

安装 pip install docker-compose
所有参数详解
http://wiki.jikexueyuan.com/project/docker-technology-and-combat/yaml_file.html

编辑规则:

选择存放路径 一般放在opt下
cd /opt
vim docker-compose.yml

规则name:
image: 镜像name
volumes: # 挂在地址
- 本地绝对地址:需要挂载绝对地址
expose:
- 内部开放端口

规则name2:
image: 镜像name
volumes: # 挂在地址
- 本地绝对地址:需要挂载绝对地址
expose:
- 内部开放端口

haproxy: # haproxy是镜像name
image: haproxy
valumes:
- 本地绝对地址:需要挂载绝对地址
links: # 依赖容器
- 规则name
- 规则name2
prots:
- 本机映射端口:容器端口 
- 本机映射端口:容器端口 

启动方式
docker-compose -f 规则文件 up -d # up -d 在后台启动 不加-d在前台启动 # 如果不加-f 规则文件 则会在docker-compose中本地寻找规则文件

=============容器中的数据持久化

数据卷


# -v 挂载参数
例如
docker run -it --rm -v /opt/data:/opt centos bash # 本地路径:容器路径 或 本地路径即可 # 只写本地路径则默认容器路径与本机挂载路径相同 # 将容器的/opt目录挂载到本地/opt/data下 例如在容器/opt下创建一个目录或者文件 在本地/opt/data也可以看到 当容器被删除 挂载创建的文件或者目录不会被删除
# 注意 一个目录可以被多个容器挂载

补充:如果在容器中创建用户 建议从后往前创建

数据卷容器
# 依赖容器
例如
docker run -it --volumes-from 已创建的容器 --name data1 centos bash # 使用--volumes-from 创建容器卷 # 利用容器卷创建的容器不受创建容器卷选择的容器依赖,及时被删除也会存在
# 当真的需要删除容器卷
docker rm -fv xxx

# 删除没有使用的所有容器
docker volume prune

============通过Dockerfile 创建镜像

# Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。
# docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。

# 注意 []中的json数组中一定要用 "" # 双引号


docker build -f /path/to/a/ # 指定文件

docker build -t debian-jdk8:v1.0 . 
# 其中-t debian-jdk8:v1.0表示打包的镜像名为debian-jdk,tag为v1.0(前面说过,tag是可以任意命名的,不一定要是这种格式),注意命令的最后有一个.,这个表示打包的上下文(其实就是Dockerfile所在目录)是在当前目录,然后目录下的Dockerfile就会被编译执行。

 

Dockerfile的基本结构
# Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。

Dockerfile文件说明
# Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。


常用的指令:
FROM:指定基础镜像,必须为第一个命令
格式:
  FROM <image>
  FROM <image>:<tag>
  FROM <image>@<digest> # digest哈希码
示例:
  FROM mysql:5.6
注:
  tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像

 


MAINTAINER: 维护者信息 # 新版使用LABEL
格式:
MAINTAINER <name>
示例:
MAINTAINER Jasper Xu
MAINTAINER sorex@163.com
MAINTAINER Jasper Xu <sorex@163.com>


RUN:构建镜像时执行的命令
RUN用于创建镜像容器中执行命令,其有以下两种命令执行方式:

shell执行
格式:
RUN <command>
多条指令推荐使用 && 连接 多Run会增加分层

exec执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
注:
  ***RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

 

ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式: # 如果路径中有空白字符建议使用第二种格式
# src如果是目录 则会复制目录下的所有内容 而不是复制整个目录
# dest必须是一个目录并且以/结尾
ADD <src>... <dest> # src 要复制的源文件或目录,支持使用通配符 被copy的文件需要在Dockfile同级目录中 dest 目标路径,即正在创建image的文件路径 建议使用绝对路径

ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
ADD test # 添加 "test" 到 当前目录



COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
格式:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"] 用于支持包含空格的路径


CMD:构建容器后调用,也就是在容器启动时才进行调用。 # 启动执行 // 如果docker执行其他命令 cmd可能会被忽略
格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先) # executable指的是以什么命令去执行后面的命令 例如["/bin/sh","-c", "echo xxx "] # 如果不使用/bin/sh 不会使用环境变量的内容
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令) # 这里的command指的是shell命令 默认是/bin/sh -c 来执行 
示例:
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
注:
  CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
*** 如果存在多个CMD 只会执行最后一条



ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去"application",只使用参数。
格式:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先) exec指令
ENTRYPOINT command param1 param2 (shell内部命令) shell 格式
示例:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
注:
   ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
# 如果需要在外部修改ENTRYPOINT设置的指令 需要增加参数 -enterpoint string 指令
# 如果ENTRYPOINT 与 CMD同时存在 CMD接收到的内容用作ENTRYPOINT的参数使用 # 一般用如果ENTRYPOINT指定容器执行命令的方式

 

LABEL:用于为镜像添加元数据
格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
  LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:
  使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

 

ENV:设置环境变量
格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe # myName 后 是value # 理论上ENV一次只能设置一个变量 可以通过 && 来执行多条命令
ENV myDog Rex The Dog
ENV myCat=fluffy


EXPOSE:指定于外界交互的端口
格式:
EXPOSE <port> [<port>...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注:
  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

 


VOLUME:用于指定持久化目录 # 只能指定容器内的路径 不能指定宿主机的路径
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:
  一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它

 

WORKDIR:工作目录,类似于cd命令
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a) // 如果有进入 如果没有创建
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:
  通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

 

USER:指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group

示例:
  USER www

注:
  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
# uid 必须要在/etc/passwd中某用户有效的UID否则docker run 会运行失败
# 默认是root用户运行

HEALTHCHECK :检测容器是否健康
# HEALTHCHECK参数:
--interval=num(default:30s) # 连接时间
--timeout=num(default:30s) # 超时时间
--start-period=num(default:0s) # 启动容器等待检测时间
--retries=num(default:0)
# 返回值:
0 seccuess
1 unhealthy
2 reserved

示例:
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1 
# CMD是关键字 必须加 # 成功执行 curl http://localhost/ 失败则退出



ARG:用于指定传递给构建运行时的变量
格式:
ARG <name>[=<default value>]
示例:
ARG site
ARG build_user=www
# 在build中使用 --build-arg
demo 
docker build --build-arg site=xxx

 


ONBUILD:用于设置镜像触发器
格式:
  ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
  当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发
# 不能执行FROM 以及 ONBUILD指令

 

以下是一个小例子:
# This my first nginx Dockerfile
# Version 1.0

# Base images 基础镜像
FROM centos

#MAINTAINER 维护者信息
MAINTAINER tianfeiyu

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD 文件放在当前目录下,拷过去会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/ 
ADD epel-release-latest-7.noarch.rpm /usr/local/

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

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0

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

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

#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD ["nginx"]

===============镜像仓 registry


yum install docker-registry
# 主配置文件 /etc/docker-distribution/registry/config.yml
# 主程序 /usr/bin/registry
# 启动目录 /usr/lib/sysyemd/system/docker-distribution.service
# 上传镜像默认存储位置 /var/lib/registry
启动 systemctl start docker-distribution # 默认监听 5000端口 在config.yml文件中配置

# 打标签
docker tag 域名(ip):端口/仓库项目名/镜像名

# 修改标签
docker tag 旧标签 新标签
例如:
docker tag mysql:5.5 mysql:latest

# 上传

docker push 域名/仓库项目名/镜像名

==============多容器串联使用示例
// 启动mysql容器 # MYSQL_ALLOW_EMPTY_PASSWORD=true 不需要密码
docker run -d --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
// 启动WordPress容器 # WORKPRESS_DB_HOST=mysql:3306指定数据库 --link mysql 链接刚才启动的mysql容器 -p 8080:80映射端口
docker run -d -e WORKPRESS_DB_HOST=mysql:3306 --link mysql -p 8080:80 wordpress

==============docker compose安装使用 (多容器并联启动)
https://www.jianshu.com/p/658911a8cff3

安装 Docker Compose

$ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

查看安装是否成功

$ docker-compose -v

Docker Compose 常用命令与配置
常见命令
- ps:列出所有运行容器
docker-compose ps
- logs:查看服务日志输出 
docker-compose logs
- port:打印绑定的公共端口,下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口
docker-compose port eureka 8761
- build:构建或者重新构建服务
docker-compose build
- start:启动指定服务已存在的容器
docker-compose start eureka
- stop:停止已运行的服务的容器
docker-compose stop eureka
- rm:删除指定服务的容器
docker-compose rm eureka
- up:构建、启动容器
docker-compose up
- kill:通过发送 SIGKILL 信号来停止指定服务的容器
docker-compose kill eureka
- pull:下载服务镜像
- scale:设置指定服务运气容器的个数,以 service=num 形式指定 // 必须使用负载均衡器才能正常使用
docker-compose scale user=3 movie=3
# 负载均衡器

version: '3'
services:
web:
image: nginx

redis:
image: redis
// 负载均衡器
lib: 
image: dockercloud/haproxy 
links: 
- web 
ports: 
- 8080:80

- run:在一个服务上执行一个命令
docker-compose run web bash

docker-compose.yml 属性
- version:指定 docker-compose.yml 文件的写法格式
- services:多个容器集合
- build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 参数
build: ./dir


build:
context: ./dir
dockerfile: Dockerfile
args:
buildno: 1

- command:覆盖容器启动后默认执行的命令
command: bundle exec thin -p 3000


command: [bundle,exec,thin,-p,3000]

- dns:配置 dns 服务器,可以是一个值或列表
dns: 8.8.8.8


dns:
- 8.8.8.8
- 9.9.9.9

- dns_search:配置 DNS 搜索域,可以是一个值或列表
dns_search: example.com


dns_search:
- dc1.example.com
- dc2.example.com

- environment:环境变量配置,可以用数组或字典两种方式
environment:
RACK_ENV: development
SHOW: 'ture'


environment:
- RACK_ENV=development
- SHOW=ture

- env_file:从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量
env_file: .env


env_file:
- ./common.env

- expose:暴露端口,只将端口暴露给连接的服务,而不暴露给主机
expose:
- "3000"
- "8000"

- image:指定服务所使用的镜像
image: java

- network_mode:设置网络模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

- ports:对外暴露的端口定义,和 expose 对应
ports: # 暴露端口信息 - "宿主机端口:容器暴露端口"
- "8763:8763"
- "8763:8763"

- links:将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况

links: # 指定服务名称:别名 
- docker-compose-eureka-server:compose-eureka

- volumes:卷挂载路径
volumes:
- /lib
- /var

- logs:日志输出信息
--no-color 单色输出,不显示其他颜.
-f, --follow 跟踪日志输出,就是可以实时查看日志
-t, --timestamps 显示时间戳
--tail 从日志的结尾显示,--tail=200

Docker Compose 其它
当服务的配置发生更改时,可使用 docker-compose up 命令更新配置
此时,Compose 会删除旧容器并创建新容器,新容器会以不同的 IP 地址加入网络,名称保持不变,任何指向旧容起的连接都会被关闭,重新找到新容器并连接上去

links
服务之间可以使用服务名称相互访问,links 允许定义一个别名,从而使用该别名访问其它服务


version: '2'
services:
web:
build: .
links:
- "db:database"
db:

image: postgres

===============镜像仓搭建 harbor

需要依赖
docker-compose

安装 Harbor
cd /etc/opt # 如果满先下载好导入
wget https://github.com/vmware/harbor/releases/download/v1.2.0/harbor-online-installer-v1.2.0.tgz

解压
tar -xf harbor-online-installer-v1.2.0.tgz

进入 
cd harbor

主要 修改harbor.cfg # 主要修改hostname(ip,域名)
hostname = redg.mydomain.com 
harbor_admin_password = Harbor12345

harbor.cfg 详解
## Configuration file of Harbor
#The IP address or hostname to access admin UI and registry service.
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
***# 指定 hostname,一般为IP,或者域名,用于登录 Web UI 界面
hostname = redg.mydomain.com 

#The protocol for accessing the UI and token/notification service, by default it is http.
#It can be set to https if ssl is enabled on nginx.
***# URL 访问方式,SSL 需要配置 nginx
ui_url_protocol = http

#Email account settings for sending out password resetting emails.
# 邮件相关信息配置,如忘记密码发送邮件
email_server = smtp.xxxxxx.com
email_server_port = 465
email_username = reg@mritd.me
email_password = xxxxxx
email_from = docker <reg@mritd.me>
email_ssl = true

##The password of Harbor admin, change this before any production use.
# 默认的 Harbor 的管理员密码,管理员用户名默认 admin
harbor_admin_password = Harbor12345

##By default the auth mode is db_auth, i.e. the credentials are stored in a local database.
#Set it to ldap_auth if you want to verify a user's credentials against an LDAP server.
# 指定 Harbor 的权限验证方式,Harbor 支持本地的 mysql 数据存储密码,同时也支持 LDAP
auth_mode = db_auth

#The url for an ldap endpoint.
# 如果采用了 LDAP,此处填写 LDAP 地址
ldap_url = ldaps://ldap.mydomain.com

#The basedn template to look up a user in LDAP and verify the user's password.
# LADP 验证密码的方式(我特么没用过这么高级的玩意)
ldap_basedn = uid=%s,ou=people,dc=mydomain,dc=com

#The password for the root user of mysql db, change this before any production use.
# mysql 数据库 root 账户密码
db_password = root123

#Turn on or off the self-registration feature
# 是否允许开放注册
self_registration = on

#Turn on or off the customize your certicate
# 允许自签名证书
customize_crt = on

#fill in your certicate message
# 自签名证书信息
crt_country = CN
crt_state = State
crt_location = CN
crt_organization = mritd
crt_organizationalunit = mritd
crt_commonname = mritd.me
crt_email = reg.mritd.me


执行脚本
./prepare
./install.sh

访问测试
对host域名进行访问测试,登录账号密码在harbor.cfg设置,默认为admin Harbor12345。harbor.cfg里设置了self_registration = on可以进行账号开放注册,设置off就只能管理员进行账号分配
# 可以设置策略 例如ip1仓库镜像推送至ip2仓库镜像
# 在系统管理下的复制管理界面 新建规则


上传下载都要先进行登录操作,否则会报错
如果 docker login报错
vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --insecure-registry=ip


vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://mk3q07hr.mirror.aliyuncs.com"]
}
# 新增一个大括号
{
"insecure-registries":["ip"] # 默认端口为80
}

sudo systemctl daemon-reload
sudo systemctl restart docker

登录命令操作为
docker login +访问的hostname

退出登录:
docker logout +访问的hostname

Push镜像到仓库创建的项目
docker push 域名/仓库项目名/镜像名:版本

Pull镜像到本地
docker pull 域名/项目名/镜像名

# 停止harbor运行
在解压harbor文件夹中
docker-compose pause # 全部暂停

# 重新启动已经暂停的
docker-compose unpause

===========================
hub.docker.com/_/registry

=====================docker集群 swarm

// 初始化
$ docker swarm init
// $ docker swarm init --advertise-addr=ip 初始化并指定ip为主节点
// 初始化成功后会生成token 复制token在其他docker中粘贴即可加入集群

// 查看集群状态
$ docker node ls

// 退出集群
$ docker swarm leave -f

// 集群中查看服务
$ docker service ls

// 集群中查看具体的服务属性
$ docker service ps 服务name

// 集群状态下启动服务
$ docker service create 
// #--name表示服务名称,--replicas表示副本任务数,--publish表示端口映射,将容器的80端口映射到物理机的80端口,nginx表示使用nginx镜像
// docker service create --name web --publish 80:80 --replicas 3 nginx

// 集群状态下删除服务
$ docker service rm -f 服务name	

// 集群状态下服务拉伸
$ docker service scale 服务name=number

// 集群状态下更新服务
// 默认配置下,Swarm一次只更新一个副本,并且两个副本之间没有等待时间。
--update-parallelism #设置并行更新的副本数目
--update-delay #指定滚动更新的间隔时间

$ docker service update --image rhel7 --update-delay 5s --update-parallelism 3 web
// #更新服务,实质上就是将原来的nginx镜像更换为rhel7镜像;

// 集群状态下创建监控服务 网页输入ip:8080即可
$ docker service create 
> --name=viz 
> --publish=8080:8080/tcp 
> --constraint=node.role==manager 
> --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock 
> visualizer


// 集群创建秘钥 
vim password
随机密码
$ docker secret create xxx password (这里的password是文件)
$ echo "xxx" | docker secret create xxx2 -

// 查看秘钥
$ docker secret ls

// 快速使用秘钥
$ docker service create --name xx --secret xxx -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/xxx mysql

===========================

镜像补充:
busybox # 不用加任何参数启动 自带一些网络工具
docker run -it --rm busybox

progrium/consul	# 配置管理中心
docker run -d -p 8500:8500 --name consul progrium/consul -server -bootstrap


nginx # nginx

haproxy # 负载均衡

sebp/elk	# 日志收集系统 # 后面附上filebeat内容
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --rm --name elk sebp/elk # 如果内存小于1G可能会报错 使用sysctl命令进行临时修改
访问 ip:9200/_search?pretty 
# filebeat下载安装(源码安装 推荐先cd /etc/opt中)
https://www.elastic.co/cn/downloads/beats/filebeat # 下载好拖到linux中
tar -zxf filebeat-7.4.0-linux-x86_64.tar.gz # 解压
cd filebeat-7.4.0-linux-x86_64

# 修改配置文件
vim filebeat.yml
enabled: true
path: # 收集日志目录地址 /var/lib/docker/containers 默认docker存放容器地址
- /var/lib/docker/containers/*/*.log
output.elasticsearch: # 连接收集log的ip
hosts: ["localhost:9200"]
# 启动
./filebeat -e -c filebeat.yml -d "publish" 

访问 ip:5601 # k8



fluent/fluentd # 用作日志收集
# 主机1
mkdir /ex_log

# 主机1
docker run -d -p 24224:24224 -p 24224:24224/udp -v /ex_log:/ex/log fluent/fluentd # -v 挂载本地文件至某处 

主机2
/etc/docker/daemon.json 中添加
{
"log-driver": "fluentd",
"log-opts": {
"fluentd-address": "开启fluent/fluentd镜像的容器ip:映射端口",
"tag": "自定义标签"
}
}

重启
systemctl daemon-reload

systemctl restart docker

# 主机1
修改 filebeat配置文件
vim /etc/opt/filebeat-7.4.0-linux-x86_64/filebeat.yml
enabled: true
path: # 收集日志目录地址 /var/lib/docker/containers 默认docker存放容器地址
- /ex_log/*.log # 前面创建的log目录

# 启动
./filebeat -e -c filebeat.yml -d "publish" 

=================== 异常处理
如果出现
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service"

yum remove docker-*

yum update

sudo yum install docker-ce

systemctl daemon-reload

systemctl restart docker

Songzhibin
原文地址:https://www.cnblogs.com/binHome/p/13701057.html