Docker——操作篇

以前学习 Docker 的笔记,主要是一些 Docker 的操作。

使用 Docker 镜像

Docker 运行容器前需要本地存在对应的镜像,如果镜像没保存在本地, Docker 会尝试先从默认镜像仓库下载(默认使用 Docker Hub 公共注册服务器中的仓库),也可以通过配置,使用自定义的镜像仓库。

获取镜像

使用 docker pull命令直接从 Docker Hub 镜像源来下载镜像。命令格式

1
2
3
4
docker pull NAME[: TAG]
# NAME 是镜像的仓库名称
# TAG 是镜像的标签
# 对于 Docker 镜像来说,如果不显式指定 TAG 则默认会选择 latest 标签,这会下载仓库中最新版本的镜像。

docker pull 命令 NAME 中还应包含 registry 默认为 docker hub,即 registry.hub.docker.com ,如果从其他 registry 中下载镜像

1
docker pull hub.c.163.com/public/ubuntu:14.04
  • pull 命令支持的选项
  • a, –all-tags=true|false: 是否获取仓库中所有镜像,默认为否

查看镜像信息

使用 images 命令列出镜像

1
docker images 

上面命令可以列出本地主机上已有镜像的基本信息

1
2
REPOSITORY                    TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hub.c.163.com/public/ubuntu 14.04 f6a575b7c805 2 years ago 237.1 MB
  • REPOSITORY 来自于哪个仓库
  • TAG 镜像的标签信息
  • IMAGE ID 镜像的 ID
  • CREATED 创建时间,说明镜像的最后更新时间
  • VIRTUAL SIZE 镜像大小

images 子命令主要支持的选项

  • -a, –all=true|false : 列出所有的镜像文件(包括临时文件),默认为false
  • –digests=true|false : 列出镜像的数字摘要值,默认为false
  • -f, –filter=[] : 过滤列出的镜像,
  • –format=”TEMPLATE” : 控制输出格式,如 ID 代表 ID 信息, Repository 代表仓库信息等
  • –no-trunc=true|false : 对输出结果中太长的部分是否进行截断,如镜像的 ID 信息,默认为 true
  • -q, –quiet=true|false : 仅输出 ID 信息,默认为 false

使用 tag 命令添加镜像标签

1
docker tag ubuntu:latest mybuntu:latest

添加一个新的 myubuntu:latest 镜像标签

使用 inspect 命令查看详细信息

1
docker inspect mybuntu:14.04

返回的是 JSON 格式的长信息,如果只需要其中一项内容时,可以使用参数 -f 来指定。

1
docker inspect -f {{".Architecture"}}

使用 history 命令查看镜像历史

1
docker history centos:7.0

过长的命令会被自动截断,可以使用 --no-trunc 选项输出完整命令

1
docker history --no-trunc centos:7.0

搜寻镜像

使用 docker search 命令可以搜索远端仓库中共享的镜像,默认搜索官方仓库中的镜像。用法为 docker search TERM ,支持的参数主要包括

  • –automated=true|false : 仅显示自动创建的镜像,默认为 false
  • –no-trunc=true|false : 输出信息不截断显示,默认为 false
  • -s, –stars=X : 指定仅显示评价为指定星级以上的镜像,默认为 0,输出所有镜像

删除镜像

使用标签删除镜像

1
docker rmi myubuntu:latest

当某个镜像有多个标签时,删除指定的标签,而不会删除标签所指向的镜像。但当镜像只有一个标签时,会将镜像彻底删除

使用镜像 ID 删除镜像

1
docker rmi IMAGEID

当有容器在运行时,无法删除,可以使用 -f 选项进行强制删除

创建镜像

创建镜像的方式有三种:

  • 基于已有镜像的容器创建
  • 基于本地模板导入
  • 基于 Dockerfile 创建

基于已有镜像的容器创建

命令格式:

1
docker commit[OPTIONS]CONTAINER[REPOSITORY[: TAG]]

主要选项包括:

  • -a, –author=””: 作者信息
  • -c, –change=[]: 提交的时候执行 Dockerfile 指令
  • -m, –message=”” : 提交消息
  • -p, –pause=true : 提交时暂停容器运行
1
docker commit -m "new file" -a "sjl" c8ac5a420141 test:1.0

基于本地模板导入

用户可以直接从一个操作系统模板文件中导入一个镜像,主要使用 docker import 命令,其命令格式为

1
docker import[OPTIONS] file|URL|-[REPOSITORY[:TAG]]

未测试

存出和载入镜像

存出镜像

如果要导出镜像到本地文件,可以使用 docker save 命令。

1
docker save -o outputpath image

演示命令

1
docker save -0 centos_7.0.tar centos:7.0

载入镜像

可以使用 docker load 命令将导出/存出的镜像导入到本地镜像库

1
docker load centos_7.0.tar

上传镜像

使用 docker push 命令上传镜像到仓库,默认上传到 Docker Hub 官方仓库,其命令格式为:

1
docker push NAME[:TAG]|[REGISTRY_HOST [:REGISTRY_PORT]/]NAME[:TAG]

未测试,注册 docker hub 或阿里云 docker 账号后进行测试

操作 Docker 容器

容器是 docker 另一个核心概念,容器是镜像的运行实时。镜像是静态只读文件,而容器带有运行时需要的可写文件层。

创建容器

新建容器

新建容器使用 docker create 命令

1
docker create -it centos:7.0

使用 docker crate 命令新建的容器处于停止状态,可以使用 docker start 命令来启动它。

启动容器

使用 docker start 命令来启动一个已经创建的容器

1
docker start ID

使用 docker ps -a 查看所有镜像 docker ps 查看一个运行中的容器

新建并启动容器

容器启动步骤

  • docker create 创建容器
  • docker start 启动容器
    使用 docker run 命令将创建容器和启动容器合并成一个步骤
    1
    docker run centos:7.0 /bin/echo 'hello world!'
    当利用 docker run 来创建并启动容器时,Docker 在后台运行操作:
  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  • 利用镜像创建一个容器,并启动该容器
  • 分配一个文件系统给容器,并在只读的镜像外面挂载一层可读写层
  • 从宿主机配置的网桥接口中桥接一个虚拟接口到容器中
  • 从网桥的地址池配置一个 IP 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被自动终止

使用 Ctrl + d 或输入 exit 命令来退出容器

常见的错误代码

  • 125 : Docker daemon 执行出错,例职指定了不支持的 Docker 命令参数
  • 126 : 所指定命令无法执行,例如权限出错
  • 127 : 容器内命令无法找到

守护态运行

正常的生产环境下,我们需要让 Docker 容器在后台以守护态(Daemonized)形式运行,此时可以通过添加 -d 参数来实现

1
docker run -d centos:7.0

获取容器的输出信息

1
docker logs id

终止容器

使用 docker stop 来终止一个运行中的容器。该命令格式为 docker stop[-t|--time[=10]][CONTAINER...]
首先向容器发送 SIGTERM 信号,等待一段超时时间(默认为 10 秒)后,再发送 SIGKILL 信号来终止 容器

1
docker stop id

docker kill

docker kill 命令会直接发送 SIGKILL 信号来强行终止容器。

Docker 容器中指定的应用终结时,容器也会自动终止
处于终止状态的容器,可以通过 docker start 命令来重新启动

重启容器

1
docker restart id

会将一个运行状态的容器先终止,然后再重启

进入容器

使用 -d 参数启动的 docker 容器,无法看到容器的信息,也无法进行操作,此时如果需要进入容器进行操作,有多种方法:

attach 命令

1
docker attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[[=true]]CONTAINER

支持三个主要选项

  • –detach-keys[=[]] : 指定退出 attach 模式的快捷键序列,默认是 CTRL -P CTRL -Q
  • –no-stdin=true|false : 是否关闭标准输入,默认是保持打开
  • -sig-proxy=true|false : 是否代理收到的系统信号给应用进程,默认为 true

exec 命令(推荐)

docker 从 1.3.0 提供了一个更加方便的 exec 命令,可以在容器内直接执行任意命令

1
docker exec [-d|--detach][--detach-keys[=[]]][-i|--interactive][--privileged][-t|--tty][-u|--user[=USER]]CONTAINER COMMAND [ARG...]

参数:

  • -i, –interactive=true|false : 打开标准输入接受用户输入命令,默认为 false
  • –privileged=true|false : 是否给执行命令以最高权限,默认为 false
  • -t, –tty=true|false : 分配伪终端,默认为 false
  • u, –user=”” : 执行命令的用户名或 ID
    1
    docker exec -it id /bin/bash

nsenter 工具

额外安装工具包

删除容器

使用 docker rm 命令来删除处于终止或退出状态的容器,其命令格式为 `docker rm[-f|–force][-l|–link][-v|–volumes]CONTAINER[CONTAINER…]
主要支持的选项

  • -f, –force=false : 是否强行终止并删除一个运行中的容器
  • -l, –link=false : 删除容器的连接,但保留容器
  • -v, –volumes=false : 删除容器挂载的数据卷

导出和导入容器

导出容器

导出容器是指导出一个已经创建的容器到一个文件,不管此时这个容器是否牌运行状态,可以使用 docker export 命令,该命令的格式为

1
docker[-o|--output[=""]]CONTAINER

通过 -o 选项来指定导出的 tar 文件名,也可以直接通过重定向来实现

导入容器

导出的文件可以使用 docker import 命令变成镜像,该文件格式为:

1
docker import [-c|--change[=[]]][-m|--message[=MESSAGE]]file|URL|-[REPOSITORY[:TAG]]

用户可以通过 -c, --change=[] 选项在导入的同时执行容器进行修改的 Dockerfile 指令

docker loaddocker import 的区别

两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也更大。
容器快照文件导入时可以重新指定标签等元数据信息

访问 Docker 仓库

仓库(Repository)是集中存放镜像的地方,分公有仓库和私有仓库。仓库存放在注册服务器上,一个注册服务器可以有多个仓库,一个仓库下可以有多个镜像

Docker Hub 公有镜像市场

登录

通过命令行执行 docker login 命令来输入用户名、密码和邮箱来完成注册和登录。注册成功后,本地用户目录的 .dockercfg 中将保存用户的认证信息

基本操作

用户无需登录即可通过 docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地

自动创建

  • 待测试

时速云镜像市场

查看镜像

访问 https://hub.tenxcloud.com , 即可看到已存在的仓库和存储的镜像

下载镜像

下载镜像使用 docker pull 命令,需要在镜像名称前添加注册服务器的具体地址。格式为:
index.tenxcloud.com/<namespace>/<repository>:<tag>

搭建本地私有仓库

使用 registry 镜像创建私有仓库

安装 Docker 后,可以通过官方提供的 registry 镜像来简单搭建一套本地私有仓库环境

1
docker run -d -p 50000:50000 registry

管理私有仓库

查看系统已经有镜像

使用 docker push 上传标记的镜像

Docker 数据管理

数据卷

数据卷本质上是将一个 Linux 中的目录映射到容器中,数据卷存在在物理机(宿主机)之上,不会因为删除容器而丢失数据。

挂载目录作为数据卷 -v

1
2
3
4
5
6
# 在 /home/sjl/ 下创建 dataVolume 目录 
[root@localhost ~]# mkdir /home/sjl/dataVolume
# 映射 dataVolume 为容器中的 home 目录
[root@localhost ~]# docker run -it --name centos -v /home/sjl/dataVolume:/home centos /bin/bash

# 在容器中的 /home 目录下创建一个文件,在宿主机中即可查看到

映射的目录必须是绝对路径,不允许是相对路径,如果目录不存在, Docker 会自动创建

数据卷权限

在启动容器时,默认的用户权限是 rw,即可读写。如果仅仅只是为了可读,需要指定为 ro

1
2
[root@localhost ~]# docker run -it --name centos -v /home/sjl/dataVolume:/home:ro centos /bin/bash

在数据卷中增加错误提示: touch: cannot touch ‘b.md’: Read-only file system

-v 参数也支持挂载一个文件到 docker 中,但是不推荐这样做

数据卷容器

数据卷容器,就是将一个容器做为数据卷,提供其他容器挂载。其方式类似于数据卷的做法,区别在于使用的是一个容器。

命令 –volumes-from

创建数据卷容器

1
2
3
4
5
[root@localhost ~]# docker -it -v /dataVolumes --name data centos
# 此时会在容器中的根目录创建一个 dataVolumes 目录

[root@localhost ~]# docker -it --volumes-from data --name c1
# 此时创建一个容器,使用数据卷容器 data 的 dataVolume 映射为本地的目录

在容器中操作的所有目录都将会在容器卷 data 中产生,即创建文件,删除文件等都在对应的容器卷中产生。

端口映射与容器互联

端口映射

从外部访问到 Docker 容器中的应用时,我们如果不将容器中的端口开放出来,就不能访问到内部应用,想要实现访问内部应用的功能就必须要将端口开放。端口开放的方法就是将容器中的端口映射为宿主机的端口,通过访问宿主机的端口从而访问容器的端口。

端口映射命令

-p(小写) -P(大写),两个参数的区别在于

  • -p(小写)需要手动指定端口
  • -P(大写)不需要手动指定端口,自动随机映射宿主机端口

-p(小写)支持的格式有:

  • IP:HostPort:ContainerPort : 指定 IP 的指定端口映射
  • IP::ContainerPort : 指定 IP 的随机端口
  • HostPort:ContainerPort(常用) : 所有 IP 的随机端口

使用 -P(大写) 随机映射 redis 的端口

1
[root@localhost ~]# docker run -it -P --name redis redis

使用 -p(小写) 映射所有宿主机的 IP 的指定端口

1
[root@localhost ~]# docker run -it -p 16379:6379 --name redis redis

–name 为容器指定名称,容器名称不能相同,否则不能创建容器。如果容器名称已经存在,要删除之前的容器才能创建。

容器互联

容器互联命令

  • –link 参数,可以让容器之间进行互联
    容器互联的意义在于,可以直接将容器进行连接,而不通过宿主机,这样就避免了端口暴露在外。常用的就是,在部署应用的容器中,连接数据库的容器,这样就可以直接连接到数据库。
    1
    2
    [root@localhost ~]# docker run -d --name db mysql:5.7
    [root@localhost ~]# docker run -d -P --name web --link db:mysql java

使用 Dockerfile 创建镜像

Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 来快速创建自定义的镜像。

基本结构

Dockerfile 分为四部分:

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

指令说明

FROM

指定所创建镜像的基础镜像,如果本地不存在,则默认会去 Docker Hub 下载指定镜像。格式为 FROM <image> 或 FROM<image>:<tag>,或 FROM <image>@<digest>
任何 Dockerfile 中的第一条指令必须为 FROM 指令,如果同一个 Dockerfile 中创建多个镜像,可以使用多个 FROM 指令。

MAINTAINER

指定维护者信息,格式为 MAINTAINER<name>,该信息会写入生成镜像的 Author 属性域中。

RUN

运行指令命令。格式为 RUN<command> 或 RUN[“executable”, “param1”, “param2”]。
每条 RUN 指令在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。

CMD

CMD 指令用来指定启动容器时默认执行的命令。它支持三种格式:

  • CMD[“executable”, “param1”, “param2”] 使用 exec 执行,是推荐的方式
  • CMD command param1 param2 在 /bin/bash 中执行,提供给需要交互的应用
  • CMD[“param1”, “param2”] 提供给 ENTRYPOINT 的默认参数
    如果用户启动容器时手动指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。

LABEL

LABEL 指令用来指定生成镜像的元数据标签信息。格式为 LABEL<key>=<value>…

EXPOSE

声明镜像内服务所监听的端口。格式为 EXPOSE<port>[<port>…]
该指令只是起到声明作用,并不会自动完成端口映射。

ENV

指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。格式为 ENV<key><value> 或 ENV<key>=<value>…
指令指定的环境变量在运行时可以被覆盖的。 docker run –env<key>=<value> built_image

ADD

该命令将复制指定的<src>路径下的内容到容器中的<dest>路径下。格式为:ADD<src><dest>,其中<src>可以是 Dockerfile 所在目录的一个相对路径(文件或目录),也可以是一个 URL,还可以是一个 tar 文件。<dest>可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径。路径支持正则表达式

COPY

复制本地主机的<src>(为 Dockerfile 所在目录的相对路径、文件或目录)下的内容到镜像中的<dest>下。目标路径不存在时,会自动创建。路径同样支持正则表达式。
当使用本地目录为源目录时,推荐使用 COPY

ENTRYPOINT

指定镜像的默认入命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。
支持两种格式:

  • ENTRYPOINT [“executable”, “param1”, “param2”](exec 中执行)
  • ENTRYPOINT command param1 param2 (shell 中执行)
    每个 Dockerfile 中只能有一个 ENTRYPOINT , 当指定多个时,只有最后一个有效。在运行时,可以被 –entrypoint 参数覆盖掉,如 docker run –entrypoint

VOLUME

创建一个数据卷挂载点。格式为 VOLUME[“/data”] 可以从本地主机或其他宫挂载数据卷,一般用来存放数据库和需要保存的数据等。

USER

指定运行容器时的用户名或UID,后续的 RUN 等指令也会使用指定的用户身份。
格式为 USER daemon

WORKDIR

为后续的 RUN、CMD 和 ENTRYPOINT 指令配置工作目录。格式为 WORKDIR/path/to/workdir
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:

1
2
3
4
5
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# 最终路径为 /a/b/c

ARG

指定一些镜像内使用的参数 (例如版本号信息等),这些参数在执行 docker build 命令时才以 –build-arg<varname>=<value> 格式传入。格式为:ARG<name>[=<default value>]

ONBUILD

配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令。格式为 ONBUILD[INSTRUCTION]

STOPSIGNAL

指令所创建镜像启动的容器接收退出的信号值。例如:

1
STOPSIGNAL signal

HEALTHCHECK

配置扎启动容器如何进行健康检查(如何判断健康与否),自 Docker 1.12 开始支持。
格式有两种:

  • HEALTHCHECK [OPTIONS] CMD command #根据所执行命令返回值是否为 0 来判断
  • HEALTHCHECK[OPTIONS] CMD command #根据所执行命令返回值是否为 0 来判断

SHELL

指定其他命令使用 shell 时默认 shell 类型。
默认值为 [“/bin/sh”, “-c”]

创建镜像

编写完成 Dockerfile 之后,可以通过 docker build 命令来创建镜像。
基本格式为 docker build [选项]内容路径,该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下的所有内容发送给 Docker 服务端,由服务端来创建镜像。

  • 如果使用非内容路径下的 Dockerfile,可以通过 -f 选项来指定其路径
  • 要指定生成镜像的标签信息,可以使用 -t 选项

使用 .dockerignore 文件

可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker 忽略匹配模式路径下的目录和文件。
例如:

1
2
3
4
5
# comment
*/temp*
*/*/temp*
tmp?
-*

使用 Dockerfile 构建 Docker 镜像

  • 明日任务,未完成在周末使用 Dockerfile 构建一次镜像

最佳实践

  • 精简镜像用途 : 尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
  • 选用合适的基础镜像 : 过大的基础镜像会造成生成臃肿的镜像
  • 提供足够清晰的命令注释和维护者个
  • 正确使用版本号
  • 减少镜像层数
  • 及时删除临时文件和缓存文件
  • 提高生成速度
  • 调整合理的指令顺序
  • 减少外部源的干扰

实战案例

使用官方镜像创建容器

busybox 的安装

1
2
[root@localhost ~]# docker pull busybox
[root@localhost ~]# docker run -it --name busybox busybox:latest

Ubuntu 的安装

1
[root@localhost ~]# docker run -it ubuntu /bin/bash

CentOS 的安装

1
[root@localhost ~]# docker run -it centos /bin/bash

Nginx 的安装

1
[root@localhost ~]# docker run -d --name nginx -p 80:80 -p 443:443 nginx

在启动 nginx 的时候,可以添加 -v 选项指定目录

Jenkins 的安

1
[root@localhost ~]# docker run -p 8080:8080 -p 50000:50000 --name myjenkins jenkins

使用断卷容器映射出 Jenkins 的操作目录

数据库相关容器的创建

  1. MySQL
    1
    [root@localhost ~]# docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql
    docker 容器互联,应用容器连接至数据库容器
  • 日志
  • 配置文件
    • 自定义配置文件
    • 使用命令传入
  1. MongoDB
    1
    [root@localhost ~]# docker run -d --name mongodb -p 27017:2 mongo