Docker 入门

什么是 Docker

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

安装 Docker

以 Ubuntu 为例,使用国内阿里云源进行安装。

1
2
3
4
5
6
7
8
9
10
# 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# 安装 GPG 证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get -y update
# 安装 Docker
sudo apt-get -y install docker-ce

基本概念

镜像(Image)

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变,是只读的。例如官方的镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。

在 Docker 中,镜像是一层一层构成的,在构建之初就是这种分层存储的架构。因此在构建镜像的时候需要格外小心不必要的文件,避免构建的镜像体积过大。

容器(Container)

镜像和容器的关系,就像是面向对象程序设计中的 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器可以拥有自己完整的root文件系统,其实质是宿主机中的一个进程,但是容器拥有自己独立的命名空间。这种隔离的特性使得使用 Docker 会变得更安全。
类似的,容器也是分层存储的,只是每个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,该层可以进行读写。

仓库(Repository)

Docker Registry 是用来集中存储、分发镜像的服务。而一个 Docker Registry 可以对应多个仓库,每个仓库可以包含多个标签(Tag),每一个标签对应着一个确定的镜像。
一般的,标签用来指定仓库的不同版本,默认使用latest作为默认。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。

使用镜像

基本操作

获取镜像
1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
  • 选项:-a参数表示下载该镜像的所有标签。
  • [Docker Registry 地址[:端口号]] 表示 Docker 镜像仓库地址,格式为<域名/IP>[:端口号],默认为 Docker Hub,可以省略。
  • 仓库名:仓库名包含了两个内容,用户名/仓库名。对于 Docker Hub,可省略用户名,此时默认为 library,即官方镜像。
  • 标签:默认为 latest
查看镜像
1
2
3
docker images
# 查看所有镜像
docker image ls -a
删除镜像
1
docker image ls rm <镜像1> [<镜像2> 。。。]

其中,<镜像>可以是镜像名、镜像 ID、镜像摘要等。

使用镜像运行容器
1
2
3
4
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 例如:
docker run --name tmp -itd ubuntu bash

使用docker run来启动一个容器

  • --name:为该容器设置一个名称,缺省为随机名称。
  • -i:交互式操作,保持标准的输入流对容器开放。
  • -t:为该容器分配一个虚拟的终端。
  • -d:保持该容器后台运行。即先不进入该容器,至于怎么进入,后面会讲到。
  • <镜像:标签>:指定镜像。若本地不存在,则从 Docker Hub 进行下载。
  • 命令:镜像启动时执行的命令,这里使用bash是希望有一个交互式的终端。

使用容器

启动容器

1
2
3
4
5
6
# 新建容器并启动
docker run ...

# 启动终止状态的容器
docker <容器> start
# container 为容器的名称,可以通过 docker ps -a 来查看所有的容器

终止容器

1
2
3
4
5
6
# 当 Docker 容器中指定的应用终结时,容器会自动终止

# 当使用 exit 退出非守护态的容器时容器立即终止

# 终止运行状态的容器
docker <容器> stop

进入容器

当使用 -d 参数启动容器时,容器会进入后台守护态运行,此时可通过两种方式进入后台

1
2
3
4
5
6
# 1. attach 命令
docker attach <容器>

# 2. exec 命令(推荐)
docker exec -it <容器> bash
# 使用 exec 命令本意是向容器中发送命令,但由于发送的是 bash,且使用了 -t 参数,所以进入了容器的终端。此时通过 exit 退出不会导致容器的终止!

删除容器

1
docker container rm <容器>

定制镜像

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
详细的设置 Dockerfile 请参见 https://yeasy.gitbooks.io/docker_practice/content/image/build.html

参考

https://yeasy.gitbooks.io/docker_practice/content/
https://juejin.im/post/5cacbfd7e51d456e8833390c