Skip to content

Docker

Docker 是什么?

Docker 可以理解为一个装应用的”容器”。想象一下,如果把应用程序比作货物:

  • 传统方式就像是把货物直接堆在船上,容易互相影响,装卸麻烦
  • 而 Docker 就像是标准的货运集装箱,不管箱子里是什么,外面都是统一的格式,方便运输和管理

不管你的应用是用 Python、Java 还是 Node.js 写的,Docker 都能把它们装进标准的”容器”里,每个应用都在自己的容器里运行,互不干扰。

在你的电脑上能运行的 Docker 容器,在其他地方也能一样运行。

为什么要用 Docker

比虚拟机更快

由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

保持开发、测试、生产环境的一致

开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。

传统的软件部署方式往往需要在目标机器上安装各种依赖软件、配置环境变量等一系列繁琐的操作,而且容易出错。Docker 容器则可以实现快速部署,只需拉取相应的 Docker 镜像(类似于已经配置好的软件包模板),然后运行容器即可启动应用。比如,要部署一个简单的 MySQL 数据库服务,以往可能需要耗费大量时间去下载安装 MySQL 软件、设置用户密码、配置数据存储路径等,而使用 Docker,只需执行简单的命令(如 docker run -d —name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql:5.7)就可以在短短几秒内启动一个配置好的 MySQL 容器,极大地提高了部署效率。

安装 Docker

在 Docker 官网中下载安装软件,安装即可。安装成功后,可在终端调用如下命令:

Terminal window
docker --version

若能输出版本号,说明 Docker 安装成功。安装完成后,最好设置国内镜像站点 registry.docker-cn.com 信息,以加快镜像下载速度。

Docker 镜像的使用

镜像是创建容器的模板。

获取镜像

使用 pull 命令可从 Docker Hub 上获取官方提供的镜像,例如:

Terminal window
docker pull centos

将会输出:

Terminal window
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest

从输出信息可以看到,pull 命令后如果不指定用户名,将会使用 library 作为用户名,软件的标签如未指定,将使用 latest。

完整的获取镜像的命令如下:

Terminal window
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

使用镜像

获取镜像后,我们就能以这个镜像为基础创建容器。例如以上面的镜像 centos 为例,可以执行:

Terminal window
docker run -it centos

其中-it表示使用交互模式终端。进入终端后,就可以像实体机器一样继续操作了。

列出已有镜像

Terminal window
docker image ls

要查看本地 Docker 相关的信息,可以通过以下几种常见的方式:

查看本地 Docker 版本信息

在终端中输入以下命令可以查看已安装的 Docker 版本:

Terminal window
docker version

该命令会分别显示客户端(Client)和服务端(Server)的版本信息,包括版本号、Go 语言版本、Git commit 信息等,这样能让你了解当前所使用的 Docker 的具体情况。

查看本地 Docker 容器信息

使用以下命令可以查看当前正在运行的 Docker 容器的详细信息,如容器 ID、名称、所使用的镜像、运行状态、端口映射等:

Terminal window
docker ps

如果想要查看更详细的信息,可以添加 -a 参数,它会显示所有容器(包括已经停止运行的容器)的信息:

Terminal window
docker ps -a

如果想深入了解某个特定容器的详细配置信息,比如容器内部的网络设置、挂载的文件系统等,可以先通过 docker ps -a 找到要查看的容器 ID,然后使用以下命令:

Terminal window
docker inspect <容器ID>

<容器ID> 替换为你实际要查看的容器的 ID,该命令会以 JSON 格式返回容器的详细配置信息,你可以从中获取到很多有用的内容。

查看本地 Docker 镜像信息

要查看本地 Docker 仓库中存储的所有镜像,可以使用以下命令:

Terminal window
docker images

该命令会显示镜像的名称、标签、镜像 ID、创建时间、大小等信息,让你对本地拥有的镜像有一个全面的了解。

类似查看容器详细配置信息的操作,若想了解某一特定镜像的详细配置信息,如镜像的分层结构、基础镜像等,可以先通过 docker images 找到要查看的镜像 ID,然后使用以下命令:

Terminal window
docker inspect <镜像ID>

<镜像ID> 替换为你实际要查看的镜像的 ID,同样会以 JSON 格式返回镜像的详细配置信息。

查看本地 Docker 网络信息

Docker 会创建多种网络供容器使用,要查看本地 Docker 创建的网络,可以使用以下命令:

Terminal window
docker network ls

该命令会显示网络的名称、ID、驱动类型、是否可跨容器连接等信息,方便你了解本地 Docker 网络的设置情况。

关闭运行中的 Docker 容器

1. 使用 docker stop 命令

这是最常用的关闭正在运行容器的方法。

首先,通过 docker ps 命令查看正在运行的容器列表,获取你想要关闭的容器的 ID 或名称。例如:

Terminal window
docker ps

该命令会显示类似如下信息:

CONTAINER ID NAME IMAGE STATUS PORTS FLOWCONTROL COUNTERS ACCESSIBILITY MEMORYUSAGE CPUUSAGE DISPATCHABLE NETWORKSTATUS APPLICABLETO DISABLEDATTRIBUTES
1234567890abcdef my_running_container ubuntu:latest Up 3 hours 80/tcp none none none 512MiB 0.5 yes connected all none

这里可以看到容器的 CONTAINER ID(如 1234567890abcdef)和 NAME(如 my_running_container)等信息。

然后,使用 docker stop 命令关闭指定的容器。可以根据容器的 ID 或名称来执行此命令,以下是两种示例:

  • 基于容器 ID 关闭:

    Terminal window
    docker stop 1234567890abcdef
  • 基于容器名称关闭:

    Terminal window
    docker stop my_running_container

docker stop 命令会向容器发送一个 SIGTERM 信号,容器在接收到该信号后,会先尝试进行一些清理工作,如关闭正在运行的应用程序、保存数据等,然后再停止运行。如果容器在一定时间内(默认为 10 秒)没有停止,docker stop 命令会再发送一个 SIGKILL 信号强制容器停止。

2. 使用 docker kill 命令

如果希望立即强制停止容器的运行,而不等待容器进行任何清理工作,可以使用 docker kill 命令。

同样,先通过 docker ps 查看正在运行的容器信息,获取容器的 ID 或名称。然后执行以下命令: - 基于容器 ID 强制停止:

Terminal window
docker kill 1234567890abcdef

基于容器名称强制停止:

Terminal window
docker kill my_running_container

docker kill 命令会向容器发送一个 SIGKILL 信号,容器接收到该信号后会立即停止运行,不会进行任何清理工作,所以这种方法可能会导致容器内的数据丢失或应用程序处于不正常状态,一般情况下不建议优先使用,除非你确定容器内的数据和应用程序状态不重要或者已经提前做好了备份和处理。

对镜像的常用命令总结

命令含义
docker image ls列出已经下载的镜像
docker image rm [选项] <镜像 1> [<镜像 2> ...]删除本地镜像

使用 Dockerfile 创建镜像

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像。Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

一个简单的例子

下面以一个简单的例子,最小化显示镜像的构建与使用。

创建一个目录,并在其中创建名为 Dockerfile 的文本文件,其内容为

Terminal window
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

在该目录中,继续执行 docker build 命令构建镜像:

Terminal window
docker build -t nginx:v1 .

构建完毕后,使用镜像创建容器:

Terminal window
docker run --name web2 -d -p 80:80 nginx:v1

现在访问 localhost,应该能看到 Nginx 的自定义欢迎界面了。

使用 Dockerfile 定制镜像

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

所谓定制镜像,就是以一个镜像为基础,也可以是空镜像(scratch),在其基础上添加新的内容。

Docker 支持使用脚本构建镜像,脚本内容写在 Dockerfile 中。关于 Dockerfile 的指令,可以到 GitHub 站点学习官方以及其他网友提供的构建脚本。

Dockerfile 的常用指令如下

指令用途案例
FROM指定基础镜像FROM nginx 以官方 nginx 镜像为基础
RUN执行命令RUN apt-get update 执行更新操作
COPY复制文件COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
CMD容器启动后运行命令CMD ["nginx", "-g", "daemon off;"] 容器启动后,前台运行 nginx 服务
ENV设置环境变量ENV NODE_VERSION 7.2.0
VOLUME定义匿名卷VOLUME /data
EXPOSE声明容器打算使用的端口
WORKDIR指定工作目录如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令

学习资料

  1. Docker 从入门到实践
  2. Docker 官方文档