Docker 实践

查看镜像和容器

  • 显示本地所有镜像:

    1
    docker image ls
  • 显示所有正在运行的容器:

    1
    docker ps
  • 显示所有容器(包括停止的):

    1
    docker ps -a

运行容器

  • 从镜像新建并运行一个容器

    1
    docker run <image_name>

    可选参数表:

    • -d:以守护模式运行。
    • -it:保持 STDIN 打开并分配一个伪终端。(建永远选上这个)
    • --name <name>:给容器起个名,易于区分。
    • -p <host_port>:<client_port> :进行端口映射,可以有多个 -p <host_port>:<client_port> 字段。也支持端口段映射,比如 -p 8000-8010:8000-8010
    • -e <key>=<value>:设置启动时环境变量。

    其它事项:

    • 一般来说,如果不指定 -d,退出终端时,容器会自动退出。
    • -d--name-p 必须在通过镜像创建容器时确定,之后一般无法改变。
    • 如果本地没有 <image_name> 镜像,会自动从远端拉去。
  • 启动一个被退出的镜像

    1
    docker start <container_name>

    可选参数表:

    • -ia:启动交互模式并附加到一个终端上。

    其它事项:

    • <container_name> 支持前缀匹配,不需要全名。
  • 附加到一个已经启动的容器中

    1
    docker exec -it <container_name> /bin/bash

    可选参数:

    • -it:保持 STDIN 打开并进入交互式 shell。
  • 在一个已经运行的容器中执行命令

    1
    docker exec <container_name> <COMMAND> <ARGS...>

    可选参数:

    • -d:后台运行命令,不进入容器。
    • -e <key>=<value>:设定环境变量。
    • -w:指定命令执行的工作目录。

容器的生命周期

容器的生命周期与主进程(PID=1 的进程)绑定,主进程退出时容器生命周期结束。

  1. 当以 docker run -it 运行容器时,主进程是终端进程,终端退出则容器退出。

  2. 当以 docker start -ia 恢复容器运行时, 主进程是终端进程,终端退出则容器退出。

  3. 当以 docker start 恢复容器运行时,主进程是一个守护进程,再使用 docker exec -it /bin/bash 启动容器终端时,终端不作为主进程,退出对容器无影响。

  4. 当以 docker run -d 运行容器时,主进程是守护进程,再使用 docker exec -it /bin/bash 启动容器终端时,终端不作为主进程,退出对容器无影响。(该情况下,主动 docker stop 容器再用 docker start -ia 恢复时,主进程是终端进程而不是守护进程)

操作容器

  • 删除容器

    1
    docker -rm <container_name>

制作镜像

直接用 container 制作

制作步骤:

  • docker run -it 一个基础镜像。

  • 用终端进行必要的修改。

  • exit 退出基础镜像并让它停止。

  • 执行 commit 制作镜像

    1
    docker commit <container_name> <image_name>[:<version>]
    • 如果不使用 [:version],默认使用 latest

用 Dockerfile 制作

用 container 制作虽然方便,但把所有操作打包到一个层非常不利于维护,所以有条件的话都建议用 Dockerfile 来制作。

一个经典的 Dockerfile 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM image_name:tag

MAINTAINER YOUR_NAME "your_email@example.com"

ENV var_name value

COPY file_path destination_directory

WORKDIR /path/to/workdir

RUN command

EXPOSE port_number

CMD ["command", "arg1", "arg2"]
  • FROM:指定基础镜像。
  • MAINTAINER:指定作者信息。
  • ENV:设置环境变量,它在构建阶段容器生命周期内均有效。
  • COPY:从宿主机拷贝文件过来。
  • WORKDIR:设置工作目录,如果不存在,会递归创建。
  • RUN:执行必要的构建命令。
  • EXPOSE:明确要暴露的端口号,但还是需要在 docker -run 时使用 -p 指定。
  • CMD:定义 docker run 时的默认命令。

制作步骤如下:

  • 准备

    建一个目录,里面创建一个名为 Dockerfile 的文件,在里面写命令。

    目录里加上可能要拷贝进去的文件。

  • 构建

    Dockerfile 的所在目录下执行以下代码。

    1
    docker build -t [<image_name>[:<version>]] <cwd>
    • -t:一般必选,指定镜像名和版本。
    • cwd:一般就写 . 了。
  • 测试

    看一下构建成功没有。

    1
    docker images

其它常用命令

  • 打 tag:

    1
    docker tag <image>:<old_version> <image>:<new_version>

    一般创建的时候你会写 <image><version>

    可以把 <version> 看成一个指针,创建 image 的时候你让 <version> 指向了它。

    docker tag 的作用就是将 <new_version> 也指向 <version> 指向的对象,用以下 cpp 代码理解:

    1
    2
    Image *old_version = new Image();
    Image *new_version = old_version;
  • 镜像保存到文件:

    1
    docker save -o <filename> <image_name>[:<version>]
  • 从文件加载镜像:

    1
    docker load -i <filename>
  • 容器保存到文件:

    1
    docker export -o <filename> <container_name>
  • 从文件将容器加载为镜像

    1
    docker import <filename> <image_name>[:<version>]

跨设备传输

推送到 DockerHub

有时候会把 image 推送到 DockerHub 上方便跨设备传输,步骤如下:

  1. 注册一个 DockerHub 账号。

  2. 终端登录 DockerHub:

    1
    docker login

    在提示下输入账号密码即可。

  3. tag 你的镜像:

    1
    docker tag <image_name>:<version> <username>/<image_name>:<version>
  4. push 它:

    1
    docker push <username>/<image_name>:<version>

注意事项:

  • 如果你的 latest 版本同时也是 1.0 版本,那么需要同时把两个标签推送上去才行:

    1
    2
    docker push <username>/<image_name>:<latest>
    docker push <username>/<image_name>:<1.0>

    但是显然只会推一次数据,第二次只是推个标签而已。

用传输介质传输

参考上面的 docker save/loaddocker export/import 并使用 U 盘或者网线等介质传输。