0%

初识 Docker

目录

初识 Docker

0 前言

最近交叉编译域控制器(ARM 架构)中的模块可执行文件时使用到了 Docker,发现其很多设计理念与 Git 都有着相似之处,本文旨在记录 Docker 的一些基本概念与常用操作。Docker 官方文档,尤其是其中的 Docker 命令行是很全面的参考。

1 概览

1.1 Docker 是什么

来看下维基百科中对 Docker 的定义:

Docker 是一个开放源代码软件,是一个开放平台,用于开发应用、交付(shipping)应用、运行应用。 Docker 允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。

简言之,Docker 是与虚拟机(Virtual Machine,例如 VMWare)类似的虚拟化技术,但更加轻量而不臃肿,便于快速地构建、打包并分发我们的应用程序及其依赖的运行环境。

一个纯净的 Ubuntu 18.04 Docker 镜像(类似系统安装盘,下文将介绍)仅仅 63.1MB,在里面安装 Git 后也才只有 196MB,将 Docker 镜像拷贝至另一台同样安装有 Docker 环境的机器上开箱即用!

小巧的 Docker 镜像

1.2 几个重要概念

在开始安装并使用 Docker 前,首先应该感性地了解下几个重要的基本概念。

1.2.1 镜像

镜像(Image)是一个只读的文件系统模板,用于生成供用户使用的系统运行环境实例(容器,下文将提到),可以类比成安装 Ubuntu 操作系统时的那个 .iso 格式的镜像文件:

Ubuntu 系统安装镜像文件

一些资料中将 Docker 镜像比作 Git 分支(Branch),我觉得并不合适,一个 Git 分支是 Git 仓库中一组历史提交(Commit)的组合,而 Docker 镜像则更像是某个 Git 分支上当前的最新提交。

1.2.2 容器

容器(Container)是运行 Docker 镜像后生成的供用户使用的系统运行环境实例,可以类比成使用 Ubuntu 操作系统镜像文件安装好的操作系统,我们可以在操作系统(Docker 容器)中执行预定义好的各种动作,比如安装软件、修改文件等,被修改过的操作系统(Docker 容器)可以被打包为新的操作系统安装文件(Docker 镜像)。

类比 Git,运行 Docker 镜像生成 Docker 容器的过程相当于在 Git 分支的某个提交上检出(checkout)新分支的过程(此时容器拥有和镜像相同的提交),我们在容器中做了某些修改并提交(docker commit)生成新镜像的过程相当于在刚刚检出的这个分支上做了一次新的提交。

Docker 镜像与容器的关系还可以类比面向对象中类与对象的关系,即,容器是镜像的一个实例(Instance)。

1.2.3 仓库

仓库(Repository)是一系列 Docker 镜像的集合,可以类比成一个 Git 代码仓库,仓库中的每个 Docker 镜像都拥有一个唯一的标签(TAG)。Git 中也有标签的概念,Git 仓库中的一个标签与某次提交相对应,再次说明了 Docker 镜像是与 Git 提交同层级的概念,而非 Git 分支。

1.2.4 注册中心

注册中心(Registry)是一系列 Docker 仓库的集合,Docker Hub(类似 GitHub 或 GitLab)是 Docker 官方的公共注册中心,上面存放了大量的 Docker 镜像供下载使用,默认配置下,docker pull 命令会从 Docker Hub 拉取镜像。此外,我们可以搭建私有的注册中心,可以类比搭建私有的 GitLab 服务器。

2 安装

在终端中直接执行下述命令即可完成 Docker 社区版的安装:

1
2
curl https://get.docker.com | sh
sudo systemctl start docker && sudo systemctl enable docker

重启 Docker 守护进程以使改动生效:

1
sudo systemctl restart docker

完成 Docker 安装后,在终端中执行下述命令并重启系统,这样可以免去每次执行 Docker 命令时需要添加 sudo 的繁琐:

1
2
sudo groupadd docker
sudo usermod -aG docker USER_NAME

3 常用命令

3.1 拉取 Docker Hub 中的远程镜像

1
docker pull REPO_NAME:TAG

例如,要拉取 Ubuntu 18.04 镜像:

1
docker pull ubuntu:18.04

3.2 加载镜像 tar 压缩文件

1
docker load -i IMAGE_TAR_FILENAME.tar

1
docker load < IMAGE_TAR_FILENAME.tar

若空间不够,需修改 /etc/docker/dameon.json 文件(不存在得话需新建),指定新的镜像加载目录,例如:

1
2
3
{
"data-root": "/home/shipeng/docker_images"
}

完成修改后需要重启 Docker 服务:

1
sudo systemctl restart docker.service

3.3 查看已经加载的镜像

1
docker images

可以得到镜像的仓库、标签、ID、创建日期、大小等信息。

3.4 使用已经加载的镜像运行一个新的容器

1
docker run -it IMAGE_ID

其中,

  • i 表示 interactive,即保持开启标准输入
  • t 表示 tty,即分配一个终端

执行完上述命令后将进入容器终端:root@CONTAINER_ID

3.5 退出当前容器终端

假如现在处于某个容器的终端中,输入下述命令来退出终端:

1
exit

3.6 列举正在运行的容器

1
docker ps

pscontainer ls 的别名,所以上述命令等价于:

1
docker container ls

3.7 停止某个正在运行的容器

1
docker stop CONTAINER_ID

3.8 删除容器

1
docker rm CONTAINER_ID

容器能够被删除的前提是该容器已经被停止。

3.9 列举所有容器(包括已经停止的容器)

1
docker ps -a

ps-f 选项用于根据提供的条件过滤输出,-q 选项用于只显示容器 ID。下面的组合命令用于删除所有已经停止的容器:

1
docker rm $(docker ps -f status=exited -q)

3.10 向正在运行的容器中拷入文件

1
docker cp LOCAL_FILE_OR_DIR CONTAINER_ID:CONTAINER_DIR

与 Linux 中的 cp 指令不同的是,即使拷贝目录,这里的 docker cp 后面也不需要添加 -R 选项。

3.11 为正在运行的容器开启一个新的 bash 终端

1
docker exec -it CONTAINER_ID /bin/bash

1
docker attach CONTAINER_ID

需要注意的是:在 docker exec 开启的新终端中执行 exit 指令只会退出终端,对容器无影响;而在 docker attach 开启的新终端中执行 exit 指令则会导致容器直接停止,而非仅仅退出终端。

3.12 将容器提交为新的镜像

假如我们对运行的容器做了一些修改,可以将其提交为新的镜像:

1
docker commit -a "AUTHOR" -m "MESSAHE" CONTAINER_ID REPO_NAME:TAG

3.13 将镜像保存为 tar 压缩文件

1
docker save -o IMAGE_TAR_FILENAME.tar CONTAINER_ID

1
docker save -o IMAGE_TAR_FILENAME.tar REPO_NAME:TAG

3.14 删除镜像

1
docker rmi CONTAINER_ID

注意,在删除容器前,需要保证依附于该镜像的所有容器都已删除。

参考

  1. Docker
  2. Docker 镜像加载原理
  3. 只要一小时,零基础入门 Docker
  4. docker docs
  5. Docker command line
  6. Docker 教程
  7. 如何在 Docker 中列出容器
Thank you for your donate!