docker 使用记录

docker 用的太水了 要学习一波怎么骚操作

安装

wget -qO- https://get.docker.com/ | sh

配置

配置 docker 服务

配置 docker 用户组

sudo usermod -aG docker USER_NAME

docker 服务默认配置 /etc/default/docker

可通过修改其中的 DOCKER_OPTS 来修改服务启动的参数

镜像

使用 docker pull 命令可以拉取镜像

docker pull NAME[:TAG]

NAME 是镜像仓库的名字, 用来区分镜像, TAG 是镜像的标签, 常用来表示版本信息

通常情况下, 描述一个镜像需要 “名字 + 标签”

对于 docker 镜像, 如果不显示指定 TAG, 则默认会选择 latest 标签

镜像仓库名称中应该添加仓库地址(即 registry, 注册服务器)作为前缀, 我们默认的是 docker hub 服务, 该前缀可以省略

下载 ubuntu 镜像:

1
2
3
4
5
6
7
8
9
10
docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
35c102085707: Pull complete
251f5509d51d: Pull complete
8e829fe70a46: Pull complete
6001e1789921: Pull complete
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

查看镜像信息

docker images

images 子命令支持如下选项

  • -a, --all=true|false 所有镜像文件(包括临时文件), 默认为 false
  • --digests=true|false 镜像的数字摘要值 默认为 false
  • -f , --filter=[] 过滤列出的镜像, 如 dangling=true 只显示没有被使用的镜像; 也可指定带有特定标注的镜像
  • --format="TEMPLATE" 控制输出格式, 如 .ID 代表 ID 信息, .Repository 代表仓库信息
  • --no-trunc=true|false 对输出结果中太长的部分进行截断, 默认为 true
  • -q, --quiet=true|false 仅输出 ID 信息

使用 tag 命令添加镜像标签

docker tag ubuntu:latest myubuntu:latest

使用 inspect 命令查看详细信息

docker inspect ubuntu:latest

使用 history 查看镜像历史

可以使用 history 命令查看各层的创建信息

docker history ubuntu:latest

搜索镜像

使用 docker search 搜索仓库中共享的镜像

docker search TERM

参数:

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

删除镜像

使用标签删除镜像

docker rmi IMAGE[IMAGE...] IMAGE 可以为标签或者 ID

当同一个镜像拥有多个标签时, docker rmi 只删除多个标签中的指定标签

当镜像只剩下一个标签时, docker rmi 会删除镜像

使用镜像 ID 删除镜像

使用 docker rmi 命令根据镜像 ID 删除时,会先尝试删除所有指向该镜像的标签, 然后删除该镜像本身

也可以是能进行区分的部分镜像 ID 串前缀

当该镜像创建的容器存在时, 镜像无法被删除

创建镜像

创建镜像的方法主要有三种: 基于已有的容器创建, 基于本地模板导入, 基于 dockerfile 创建

导出和载入镜像

docker save, docker load

save 导出镜像到文件

docker save -o ubuntu_14.04.tar ubuntu:latest

载入镜像

docker load --input ubuntu_14.04.tar

docker load < ubuntu_14.04.tar

上传镜像

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

容器

创建容器

新建容器

docker create

  • -l, --label=[] 以键值对的方式制定容器的标签信息
  • --label-file=[] 从文件中读取标签信息

docker create -it ubuntu:latest

使用 docker create 命令创建的容器处于停止状态, 可以使用 docker start 启动

启动容器

docker start

新建并启动容器

docker run

docker run ubuntu /bin/echo/ 'hello world'

当使用 docker run来创建并启动容器时, docker 在后台运行的操作:

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

如下命令启动一个 bash, 允许用户进行交互

docker run -it ubuntu:latesd /bin/bash

  • -t 让 docker 分配一个伪终端并绑定到容器的标准输出上
  • -i 让容器的标准输入保持打开

常见错误码

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

在执行 docker run 的时候 添加 -rm 命令, 则容器在停止后会立即删除

–rm 和 -d 参数不能同时使用

后台运行

可以通过添加 -d 参数实现

停止容器

docker stop[-t|--time[=10]][CONTAINEWR..]

首先向容器发送 SIGTERM 信号, 等待一段时间(默认 10 秒) 后, 再发送 SIGKILL 信号来停止容器

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

docker restart

进入容器

attach

attach 是 docker 自带的命令

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

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

当多个窗口同时使用 attach 命令连到同一个容器的时候, 所有窗口都会同步显示. 当某个窗口因命令阻塞时, 其他窗口也无法执行操作.

exec

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

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

例如 进入刚创建的容器并启动一个 bash

docker exec -it ID /bin/bash

nsenter 工具

在 util-linux 软件包版本 2.23+ 中包含 nsenter 工具

删除容器

docker rm [-f | --force] [-l | --link] [-v |--volumes] CONTAINER[CONTAINER...]

  • -f, --force=false rm -f
  • -l, --link=false 删除容器的链接, 但保留容器
  • -v, --volumes=false 删除容器挂载的数据卷

容器的导入和导出

导出

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

导入

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

  • -c, --changes 在导入时执行对容器修改的 dockerfile 指令

数据管理

  • 数据卷 容器内数据直接映射到本地主机环境
  • 数据卷容器 使用特定容器维护数据卷

数据卷

数据卷是一个可供容器使用的特殊目录, 将操作系统目录直接映射进容器, 类似于 linux 下的 mount 操作

  • 数据卷可以在容器之间共享和重用
  • 对数据卷内数据的修改会立马生效, 无论是容器内操作还是本地操作
  • 对数据卷的更新不会影响镜像, 解耦应用和数据
  • 卷会一直存在, 直到没有容器使用, 可以安全卸载

在容器内创建一个数据卷

在用 docker run 命令的时候, 使用 -v 标记可以在容器内创建多个数据卷, 多次重复使用 -v 可以创建多个数据卷

挂载一个主机目录作为数据卷

docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

挂载主机的 /src/webapp 目录到容器的 /opt/webapp 目录

也可通过 ro 指定为只读

docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

这样, 容器内则无法修改挂载的数据

挂载一个本地主机文件作为数据卷

docker run -rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

这样就可以记录在容器输入过的历史命令

若直接挂在一个文件到容器, 使用文件编辑工具, 包括 vi 或者 sed--in-place 的时候, 可能会造成文件 inode 的改变, 从 docker 1.1.0 起, 会导致错误发生, 所以推荐的方式是直接挂载文件所在的目录

数据卷容器

如果需要在多个容器之间共享一些持续更新的数据, 最简单的方式是使用数据卷容器.

数据卷容器也是一个容器, 但是它的是专门用来提供数据卷供其它容器挂载

首先, 创建一个数据卷容器 dbdata, 并在其中创建一个数据卷挂载到 /dbdata

docker run -it -v /dbdata --name dbdata ubuntu

然后在其它容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷

创建 db1 和 db2 两个容器, 并从 dbdata 容器挂载数据卷

docker run -it --volumes-from dbdata --name db1 ubuntu

docker run -itd --volumes-from dbdata --name db2 ubuntu

使用 --volumes-from 参数所挂载的数据卷的容器自身并不需要保持在运行状态

如果删除了挂载的容器( 包裹 dbdata db1 db2), 数据卷并不会被删除

如果要删除一个数据卷, 必须在删除最后一个还挂载着它的容器时显式的使用 docker rm -v 来指定同时删除关联的容器

利用数据卷容器来迁移数据

备份

docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata

  • 首先使用 ubuntu 镜像创建了一个容器 worker
  • 使用 --volumes-from dbdata 让 worker 容器挂载 dbdata 容器的数据卷
  • 使用 -v$(pwd):/backup 来挂载本地的当前目录到 worker 容器的 /backup
  • worker 启动后, 使用 tar cvf /backup/backup.tar /dbdata 将 /dbdata 下内容备份为容器内的 /backup/backup.tar, 即宿主机当前目录下的 backup.tar

恢复

创建一个带有数据卷的容器 dbdata2

docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然后创建另一个新容器, 挂在 dbdata2 的容器, 并解压备份文件到所挂载的容器卷中

docker run --volumes-from dbdata2 -v $(pwd):/backup tar xvf /backup/backup.tar

端口映射和容器互联

从外部访问容器应用

通过 -p-P 参数来指定端口映射

  • -P docker 会随机映射一个 49000 - 49900 的端口到内部容器开放的网络端口
    - -p 指定要映射的端口, 并且在指定的端口上只可以绑定一个容器, 支持的格式: IP: HostPort: ContainerPort| IP: :ContainerPort | HostPort: ContainerPort

映射所有接口地址

使用 Host: Port: ContainerPort 格式将本地的 5000 端口映射到容器的 5000 端口

docker run -d -p 5000:5000 training/webapp python app.py

映射到指定地址的指定端口

使用 IP: HostPort: ContainerPort 格式指定映射使用一个特定地址, 比如 localhost

docker run -d -p 127.0.0.1:5000:5000 training/webapp python addp.py

映射到指定地址的任意端口

使用 IP: : ContainerPort 绑定 localhost 的任意端口到容器的 5000 端口, 本地主机会自动分配一个端口

docker run -d -p 127.0.0.1::5000 training/webapp python web.py

查看映射端口配置

使用 docker port 命令来查看当前映射的端口配置, 也可以查看到绑定的地址

docker port ubuntu 5000

容器有自己的内部网络和 IP 地址, 使用 docker inspect ContainerID 可以获取容器的具体信息

互联机制实现便捷访问

容器的互联是一种让多个容器中应用进行快速交互的方式, 它会在源和接收器之间创建链接关系, 接收容器可以通过容器名快速访问到源容器, 而不用指定具体的 IP 地址

自定义容器命名

连接系统根据容器的名称来执行, 因此首先要起一个好名字

使用 --name 可以为容器自定义命名

容器的名称是唯一的

如果已经有一个名字了, 需要先删除之前创建的同名容器

容器互联

使用 –link 参数可以让容器之间安全的进行交互

–link 参数的格式为 --link name: alias 其中 name 是要链接的容器的名称, alias 是这个链接的别名

创建一个新的数据库容器

docker run -d --name db training/postgres

创建一个 web 容器, 并将它链接到 db 容器

docker run -d -P --name web --link db:db trainling/webapp python web.py

此时 db 容器和 web 容器建立互联关系

docker 通过两种方式为容器公开信息

  • 更新环境变量
  • 更新 /etc/hosts 文件

其中 DB_ 开头的环境变量是供容器链接 db 容器使用的, 前缀采用大写的链接别名

除了环境变量之外, Docker 还添加 host 信息到父容器的 /etc/hosts文件

Dockerfile

基本结构

Dockerfile 由一行行命令语句组成, 支持 # 开头的注释

一般而言 Dockfile 分为四部分:

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

指令

指令的一般格式为 INSTRUCTION arguments, 指令包括 FROM MAINTAINER RUN

FROM

  • 说明:指定该镜像的基础镜像
  • 格式如:FROM <image>FROM <image>:<tag>
  • 示例:FROM centos:7
  • 注意:FROM一般出现在文件头,且每个镜像都需要有一个 FROM来指定基础镜像。

MAINTAINER

  • 说明:指定作者信息
  • 格式如:MAINTAINER <name>
  • 示例:MAINTAINER afreto ""

RUN

  • 说明:在构建镜像时执行脚本
  • 格式如:RUN 或RUN [“exec”, “par1”, “par2”], 后一个指令会被解析成 json 数组, 因此必须使用双引号 , 前者默认将在 shell终端中运行命令. 后者则使用 exec 执行, 不会启动 shell环境, 指定使用其它终端类型可以通过第二种方式实现, 如 RUN[“/bin/bash”,”-c”,”echo hello”]
  • 示例:RUN ls -l(以详细信息方式列表当前目录下的文件,跟在 shell 终端运行一样)

每条指令会在当前镜像的基础上执行指定命令, 并提交为新镜像

命令过长可以使用 \ 来换行

CMD

  • 说明:用来指定启动容器时默认执行的命令.
  • 格式:
    • CMD["executable","param1","param2"], 使用 exec 执行, 是 推荐的方式
    • CMD command param1 param2/bin/sh 中执行, 提供给需要交互的应用
    • CMD["param1", "param2"] 提供给 ENTRYPOINT 的默认参数
  • 示例:CMD ["ls", "-l"]
  • 注意:一个 Dockerfile 中只有一条 CMD,如果有多条只执行最后一条;在运行容器时如果用户指定了运行命令则 Dockerfile 中的 CMD 将被覆盖。

LABEL

  • 说明: 用来指定生成镜像的元数据标签
  • 格式: LABEL<key>=<value><key>=<value>...
  • 示例: LABEL version="1.0"

ENTRYPOINT

  • 说明:指定镜像的默认入口命令, 该入口命令会在启动容器时作为根命令执行
  • 格式如:ENTRYPOINT ["exec", "par1", "par2"]ENTRYPOINT command par1 par2
  • 示例:ENTRYPOINT ["catalina.sh", "run"]
  • 注意:一个 Dockerfile 中只有一条 ENTRYPOINT,如果有多条只执行最后一条, 在运行时可以被 --entrypoint 参数覆盖. 如docker run --entrypoint

EXPOSE

  • 说明:让 Docker 暴露容器的端口号,供其他容器使用,在宿主机以外的网络中是无法使用的
  • 格式如:EXPOSE <port> ...
  • 示例:EXPOSE 8080
  • 注意:
    • 该指令只起到声明作用, 并不会完成端口映射
    • 在 Docker 中有两种暴露端口的概念,一种叫 EXPOSE隐式暴露,只供 Docker 服务内部使用;另一种叫 PUBLISH显式暴露,供外部网络使用,PUBLISH只是一个概念在 Dockerfile 中没有这个指令。
    • EXPOSE只在 Dockerfile 中出现
    • PUBLISH没有该指令而是通过 docker run命令的参数 -p-P或在 docker-compose中的 ports来体现
    • -P:大写是属于自动映射,将 Dockerfile 中 EXPOSE所暴露的所有端口分别映射到宿主机的随机端口,每次启动或重启容器时端口都可能有所不同
    • -p:小写是属于固定映射,格式如:-p 宿主端口:容器端口,宿主端口和容器端口可以是纯数字也可以是一个范围,如:-p 8060-8080:8060-8080,意为将宿主机的 8060(含)到 8080(含)的端口映射到容器的 8060(含)到 8080(含)端口,需要注意的是在使用范围时,宿主端口个数应该与容器端口个数匹配;但上面这个例子可以写成:-p 7060-7080:8060-8080,这样宿主的端口就在 7060-7080范围内

ENV

  • 说明:指定环境变量,在 Dockerfile 文件中的后续代码中使用,在容器运行时也可以使用

  • 格式如:ENV <key> <value>

  • 示例:ENV tomcat_home /web/tomcat/

    指令指定的环境变量在运行时可以被覆盖, 如

    docker run --env <key>=<value> IMAGE

ADD

  • 说明:复制指定的 <src> 路径下的内容到容器中 <dest>路径下(复制文件夹?)
  • 格式如:ADD <src> <dest>
  • 示例:ADD web.jar /web.jar
  • 注意:复制指定的 <src>到容器中的 <dest><src>可以是 Dockerfile 所在目录的一个相对路径,也可以是一个 URL,也可以是一个 tar文件(tar文件将自动解压成文件目录)

COPY

  • 说明:添加文件(夹)到容器
  • 格式如:COPY <src> <dest>
  • 示例:COPY web.jar /web.jar
  • 注意:与 ADD功能相似,只是不能指定 URL,使用本地文件(夹)为源文件时,推荐使用 COPY

VOLUME

  • 说明:创建挂载点

  • 格式如:VOLUME [path]

  • 示例:VOLUME ["/datas"]

  • 注意:

    • VOLUME在原理和概念上与 EXPOSE差不多,都是属于供容器与容器间使用

    • 通过 VOLUME挂载的卷可以供其他容器使用

    • 举例说明:

      • 创建一个 Dockerfile 来构建一个镜像,内容如下:

        1
        2
        FROM centos
        VOLUME ["/web/images", "/web/files"]
      • 构建镜像

        1
        docker build -t "zsl131/test01" .
      • 启动容器

        1
        docker run -d --name test-root
      • 可以使用命令:docker inspect test-root来查看容器详细信息,在 Mounts部份可以看到两个挂载点:/web/images/web/files

      • 启动另一个容器来共用这两个挂载卷

        1
        docker run -it --name test-1 --volumes-from test-root centos

        注意:使用 --volumes-from来指定挂载点,这时容器 test-roottest-1里面都分别有挂载卷 /web/images/web/files,可以启动任意多个容器使用 --volumes-from来共用这些挂载卷,这些容器可以来自不同的镜像。当任何一个容器中的挂载卷中的文件发生变化时其他容器挂载卷中的内容也随之改变。

        容器 test-root即使已经停止也可以在启动其他容器时使用 --volumes-from test-root来挂载这些卷,只要 test-root不被删除,不过如果 test-root真被删除还可以使用 --volumes-from test-1,因为容器 test-1中还存在我们所需要的挂载卷,换句话说这些挂载卷永远存在直到所有使用这些挂载卷的容器都被删除。

      • VOLUMEdocker run参数 -v是有区别的。docker run -v /host/web/images:/web/images -v /host/web/files:/web/files:rw是将容器内的 /web/images挂载到宿主机的 /host/web/images目录上;将容器内的 /web/files挂载到宿主机的 /host/web/files目录上,rw表示可读写。

WORKDIR

  • 说明:设置工作目录
  • 格式如:WORKDIR /path
  • 示例:WORKDIR /web
  • 注意:可以使用绝对路径,也可以使用相对路径,设置之后的所有操作都将在这个目录下完成

RUNCMDENTRYPOINT执行脚本的指令

  • 三个指令都是执行脚本
  • RUN是在创建镜像是执行,即使用 docker build命令时执行,在一个 Dockerfile 里面可以有多个 RUN
  • CMDENTRYPOINT是在运行容器时执行,即使用 docker run命令时执行,这两个指令在 Dockerfile 中都只有最行一条被执行
  • CMD在使用 docker run时可以加参数将 Dockerfile 中的 CMD覆盖
  • ENTRYPOINT在 Dockerfile 中出现后就一定会在 docker run时被执行,不必担心会被其他参数所覆盖。

ADDCOPY拷贝文件(夹)到容器

  • ADD拷贝文件(夹)时可以指定本地文件、远程 URL 地址,如果拷贝的是 tar文件时将会被自动解压成文件夹
  • COPY拷贝文件(夹)时不可以指定远程 URL 地址,拷贝 tar文件也不会被自动解压成文件夹,在拷贝本地文件时建议使用 COPY

USER

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

ARG

  • 说明 指定一些镜像内使用的参数, 这些参数在执行 docker build 命令时以 --build-arg<varname>=<value>格式传入
  • 格式 ARG <name>[=<deafult value>]

创建镜像

写完 Dockerfile 后, 使用 docker build创建镜像

  • -f 指定 Dockfile 路径
  • -t 指定生成镜像的标签信息

配置代理

docker build . --build-arg "HTTP_PROXY=http://127.0.0.1:1087/" --build-arg "HTTPS_PROXY=http://127.0.0.1:1087/" --network host -t smtp:1