Docker学习总结

Docker 中的三个基本概念

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

镜像

是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

镜像不包含任何动态数据,其内容在构建之后也不会改变

容器

是镜像的运行时实例 - 实际执行时镜像会在内存中变成什么。默认情况下,它完全独立于主机环境运行,仅在配置为访问主机文件和端口的情况下才执行此操作。

非root用户执行docker

1
2
3
4
5
6
7
1. 创建docker组,一般是存在的。
sudo groupadd docker
2. 将当前用户添加到docker组
sudo usermod -aG docker $USER
3. 注销当前登陆用户,从新登陆
4. 验证是否可以行
docker ps

命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
docker build -t friendlyname .# 使用此目录的 Dockerfile 创建镜像
docker run -p 4000:80 friendlyname # 运行端口 4000 到 90 的“友好名称”映射
docker run -d -p 4000:80 friendlyname # 内容相同,但在分离模式下
docker ps # 查看所有正在运行的容器的列表
docker stop <hash> # 平稳地停止指定的容器
docker ps -a # 查看所有容器的列表,甚至包含未运行的容器
docker kill <hash> # 强制关闭指定的容器
docker rm <hash> # 从此机器中删除指定的容器
docker rm $(docker ps -a -q) # 从此机器中删除所有容器
docker images -a # 显示此机器上的所有镜像
docker rmi <imagename> # 从此机器中删除指定的镜像
docker rmi $(docker images -q) # 从此机器中删除所有镜像
docker login # 使用您的 Docker 凭证登录此 CLI 会话
docker tag <image> username/repository:tag # 标记 <image> 以上传到镜像库
docker push username/repository:tag # 将已标记的镜像上传到镜像库
docker run username/repository:tag # 运行镜像库中的镜像
docker stack ls # 列出此 Docker 主机上所有正在运行的应用
docker stack deploy -c <composefile> <appname> # 运行指定的 Compose 文件
docker stack services <appname> # 列出与应用关联的服务
docker stack ps <appname> # 列出与应用关联的正在运行的容器
docker stack rm <appname> # 清除应用
docker-machine create --driver virtualbox myvm1 # 创建 VM(Mac、Win7、Linux)
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10
docker-machine env myvm1 # 查看有关节点的基本信息
docker-machine ssh myvm1 "docker node ls" # 列出 swarm 中的节点
docker-machine ssh myvm1 "docker node inspect <node ID>" # 检查节点
docker-machine ssh myvm1 "docker swarm join-token -q worker" # 查看加入令牌
docker-machine ssh myvm1 # 打开与 VM 的 SSH 会话;输入“exit”以结束会话
docker-machine ssh myvm2 "docker swarm leave" # 使工作节点退出 swarm
docker-machine ssh myvm1 "docker swarm leave -f" # 使主节点退出,终止 swarm
docker-machine start myvm1 # 启动当前未运行的 VM
docker-machine stop $(docker-machine ls -q) # 停止所有正在运行的 VM
docker-machine rm $(docker-machine ls -q) # 删除所有 VM 及其磁盘镜像
docker-machine scp docker-compose.yml myvm1:~ # 将文件复制到节点的主目录
docker-machine ssh myvm1 "docker stack deploy -c <file> <app>" # 部署应用

Docker命令

1
2
3
4
5
6
7
8
9
10
11
12
13
docker save -o <localfilename> <flename> #导出镜像到本地文件
docker load --input <filename> #从导出的本地文件中再导入到本地镜像库
docker load < <filename> #同上,导入镜像以及其相关的元数据信息(包括标签等)(生成镜像文件)
docker run -d ... # 使docker容器在后台以守护态形式运行
docker export <container id> > <localfilename> # 将本地的某个容器导出
docker import - <repository:tag> # 将容器快照文件导入为镜像 (生成镜像快照)
docker load 和 docker import 的区别:
docker import 将丢弃所有的历史记录和元数据信息(仅保存容器当时的快照状态),
docker load 将保存完整记录,体积较大
docker import 导入时可以重新指定标签等元数据信息
docker image ls --digests # 列出所有镜像的摘要
docker image rm <id、repository:tag> # 删除镜像,在通过id删除时,可以指定前3个字符以上,但是要能足够用于区分别的镜像
docker image rm <digest> # 精确删除

Union FS 是有最大层数限制的,比如 AUFS,一个镜像不能超过127层

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  • 从地址池配置一个 ip 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止

仓库名、标签均为<none>的镜像,被称为虚悬镜像

显示虚悬镜像:docker image ls -f dangling=true

删除虚悬镜像:docker image prune

docker 中的过滤器

在docker image ls还支持使用过滤器参数 –filter或-f

  • since 在某个镜像之后建立的镜像
  • before在某个镜像之前建立的镜像
  • dangling未打开标签

镜像是多层存储,每一层是在前一层的基础上进行的修改;而容器同样也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层。

镜像的定制实际上就是定制每一层所添加的配置、文件.

在构建Dockerfile时,如果使用了scratch为基础镜像,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始,这样减少了镜像体积。

从标准输入中读取Dockerfile

1
2
3
docker build - < Dockerfile

cat Dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为Dockerfile,并开始构建。这种形式由于直接从标准输入中读取Dockerfile的内容,它没有上下文,因此不以像其他方法那样将文本文件Copy进镜像之类的事情

ADD中更高级的复制文件

ADD指令将会自动解压缩这个压缩文件到<目标路径>

COPY和ADD指令选择时遵循的原则

所有文件复制均使用COPY指令,仅在需要自动解压缩的场合使用ADD

Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用upstart/systemd 去启动后台服务,容器内没有后台服务的概念。
启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义。
当使用ENTRYPOINT后,CMD的内容将会作为参数传给ENTRYPOINT。

EXPOSE指令是声明运行时容器提供的服务端口

WORKDIR可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如果目录不存在,WORKDIR自动创建目录。

USERWORKDIR都是改变环境状态并影响以后的层。WORKDIR是改变工作目录,USER则是改变之后层的执行RUNCMD以及ENTRYPOINT这类命令的身份。

HEALTHCHECK支持下列选项:

  • –interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
  • –timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • –retries=<次数> :当连续失败指定次数后,则将容器状态视为_unhealthy_,默认3次。

CMDENTRYPOINTHEALTHCHECK三者的共同点:在Dockerfile文件中只可以出现一次,如果出现多次,只有最后一个生效。

镜像迁移

1
2
3
docker export container_id > export_filename.tar

cat export_filename.tar | docker import - repository:tag

此处利用了Linux中的管道,将一个镜像文件从一台机器迁移到另一台机器

docker attach和docker exec的区别

相同点:

  • 两者都可以使用-d、-i参数,在同时使用这两个参数时,都是进入bash
  • -i参数是没有分配伪终端,但命令执行结果仍然返回

不同点:

  • 在使用attach进入伪终端,输入exit退出时,会导致容器的停止
  • exec进入终端,输入exit退出时,不会导致容器的停止

容器的操作

1
2
docker container rm 容器名称
docker container prune # 清理所有处于终止状态的容器

如果要删除一个运行中的容器,可以添加-f参数。Docker 会发送SIGKILL信号给容器。

Docker 数据管理

在容器中管理数据主要有两种方式:

  • 数据卷(Volumes)
  • 挂载主机目录(Bind mounts)

数据卷

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性:

  • 数据卷可以在同期之间共享和重用
  • 对数据卷的修改会立即生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认一直存在,即使容器被删除

数据卷操作命令

1
2
3
4
docker volume create <volumename> # 创建一个数据卷
docker volume ls # 查看所有数据卷
docker inspect <contrainer name> # 查看容器的信息
docker volume rm <volumename> # 删除数据卷

在用docker run命令的时候,使用 –mount标记来将数据卷挂载到容器里,在一次docker run中可以挂载多个数据卷。

数据卷是被设计用来持久化数据的,它的声明周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收机制。

使用网络

在容器中运行一个网络应用,要让外部也可以访问这些应用,可以通过-P或-p参数来执行端口映射

在使用-P标记时,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口。

Compose中的两个重要概念

  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义

docker-compose命令

命令选项

  • -f, –file FILE 指定使用的 Compose 模板文件,默认为docker-compose.yml,可以多次指定。
  • -p, –project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
  • –x-networking 使用Docker的可拔插网络后端特性
  • –x-network-driver DRIVER 指定网络后端的驱动,默认为bridge
  • –verbose 输出更多调试信息
  • -v, –version打印版本并退出