一、docker与容器
虚拟化既可以通过硬件模拟来实现,也可以通过操作系统软件来实现。容器计数充分利用了操作系统本身已有的机制和特性,可以实现远超传统虚拟机的轻量级虚拟化

1.1 什么是docker?

docker 是基于Go语言实现的开源容器项目,官网 docker.com。Linux各大发行版、macOS,windows等都已支持docker
构想:build,ship and run any app,anywhere。即通过对应用的封装(packaging)、分发(distribution)、部署(deployment)、运行(runtime)生命周期进行管理,达到应用组件级别的“一次封装,到处运行”【应用组件:既可以是一个web应用、一个编译环境,也可以是一套数据库平台服务,甚至是一个操作系统或集群】

1、Linux容器技术

linux容器(Linux Contains,LXC)技术。
“容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立地组之间平衡有冲突地资源使用需求。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心CPU本地运行指令,而不需要任何专门地解释机制。此外,也避免了准虚拟化(para-virtualization)和系统带哦用替换中地复杂性”

2、从Linux容器到Docker

Docker进一步优化了容器地使用体验:首先,提供了各种容器管理工具(分发、版本、移植等);其次,通过引入分层文件系统构建和高效地镜像机制,降低了迁移难度。
可以将docker理解为一种轻量地沙盒,每个容器内运行着一个应用,不同地容器相互隔离,容器之间可以通过网络互相通信。容器自身对系统资源地额外需求也十分有限

1.2 Docker与虚拟化

虚拟化(virtualization)技术是一个通用地概念,在不同地领域有不同的理解。在计算领域,一般指的是计算虚拟化(computing virtualization),或通常说的服务器虚拟化
“在计算机技术中,虚拟化是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用比原本的组态更好的方式来应用这些资源”
00 Docker基础 - 图1

二、核心概念与安装配置

2.1 核心概念

  • Docker三大核心概念:镜像、容器和仓库

    1、docker镜像

  • 类似于虚拟机镜像,可以理解为一个只读的模板,一个镜像可以包含一个基本的操作系统环境。里面只安装了用户需要的软件

  • 镜像是创建docker容器的基础。通过版本管理和增量的文件系统,docker提供了一套十分简单的机制来创建和更新现有的镜像

    2、docker容器

  • 类似于一个轻量级的沙箱。docker利用容器来运行和隔离应用

  • 容器是从镜像创建的应用运行实例,可以启动、开始】停止、删除,容器之间彼此相互隔离、互不可见
  • 注意:镜像自身是只读的。容器从镜像启动的时候,会在镜像的最上层创建一个可写层

    3、docker仓库

  • 类似于代码仓库,是docker几种存放镜像文件的场所

  • 根据所存储的镜像公开分享与否,docker仓库可以分为公开仓库(public)私有仓库(private)

    2.2 安装docker引擎

  • docker引擎是使用docker容器的核心组件,可以在主流的操作系统和云平台使用

  • 目前docker支持docker引擎、docker hub、docker cloud等
    • docker引擎:包括支持在桌面系统或云平台安装docker
    • dockerhub:官方提供的云托管服务
    • docker cloud:官方提供的容器云服务,可以完成容器的部署与管理

      2.2.1 Ubuntu环境下安装Docker

      1、安装docker软件源和GPG密钥

      ```r

      1、系统要求

      通过如下命令检查自己的内核版本详细信息,UBUNTU 16.04 LTS以上

      uname -a

      或者

      cat /proc/version

如果是Unbuntu 16.04 LTS版本,为了让Docker使用aufs存储,安装如下两个安装包

sudo apt-get update sudo apt-get install -y linux-image-extra-$(uname-r) linux-image-extra-virtual

sudo apt-key fingerprint

获取当前操作系统的代号

lsb_release -cs

focal

旧版本的docker称为docker或者docker-engine,使用以下命令卸载旧版本

$ sudo apt-get remove docker \ docker-engine \ docker.io

  1. Ubuntu 16.04 以上的docker ce默认使用`overlay2`存储层驱动,无需手动配置<br />使用APT安装<br />由于`apt`源使用https以确保软件下载过程中不被篡改,因此首先添加使用https传输的软件包以及CA证书
  2. ```bash
  3. sudo apt-get update
  4. sudo apt-get install \
  5. apt-transport-https \
  6. ca-certificates \
  7. curl \
  8. software-properties-common

添加软件源的GPG密钥和Docker软件源

  1. curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
  2. # OK
  3. # 官方源
  4. # $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  5. # 然后需要向source.list中添加Docker软件源
  6. sudo add-apt-repository \
  7. "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
  8. $(lsb_release -cs) \
  9. stable"
  10. # 官方源
  11. # $ sudo add-apt-repository \
  12. # "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  13. # $(lsb_release -cs) \
  14. # stable"
  15. # 以上命令会添加稳定版本的Docker CE APT 镜像源
  16. sudo apt-get update # 再次更新apt软件包缓存

2、开始安装Docker

  1. # 更新apt软件包缓存,并安装docker-ce
  2. sudo apt-get update
  3. sudo apt-get install -y docker-ce
  4. # 在测试或开发环境中docker为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu可以使用这套脚本安装:
  5. curl -fsSL get.docker.com -o get-docker.sh
  6. sudo sh get-docker.sh --mirror Aliyun
  7. # 执行命令后,脚本会自动做好准备工作,并且把docker ce的edge版本安装在系统中

3、启动Docker CE

sudo systemctl enable docker
sudo systemctl start docker

# Ubuntu14.04用这个
sudo service docker start

4、建立docker

默认情况下,docker命令会使用unix socket与docker引擎通讯,而只有root用户和docker组的用户才可以访问docker引擎的unix socket。出于安全考虑,将需要使用docker的用户加入docker用户组

# 1、建立docker组
sudo groupadd docker

# 2、将当前用户加入docker组
sudo usermod -aG docker USERname
# 退出当前终端并重新登录,进行如下测试

# 测试Docker是否安装正确
docker run hello-world

三、使用镜像

3.0 镜像加速器

# Ubuntu 16.04+ 以上
# 在/etc/docker/daemon.json中写入如下内容,文件不存在就新建

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

# 之后重新启动服务
sudo systemctl daemon-reload
sudo systemctl restart docker

3.1 获取镜像

从Docker镜像仓库获取镜像的命令是docker pull,命令格式:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
  • 镜像名称的格式:
    • Docker镜像仓库地址:<域名/IP>[:端口号]。默认地址的是Docker Hub
    • 仓库名:两段式名称,<用户名>/<软件名>

      3.1.1 pull 镜像

      ```bash

      例如

      docker pull ubuntu:20.04

20.04: Pulling from library/ubuntu

bf5d46315322: Pull complete

9f13e0ac480c: Pull complete

e8988b5b3097: Pull complete

40af181810e7: Pull complete

e6f7c7e5c03e: Pull complete

Digest:sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae973d643fbbe

Status: Downloaded newer image for ubuntu:16.04

从下载的过程中可以看到之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层去下载,并非单一文件
<a name="mTE7e"></a>
### 3.1.2 运行
有了镜像之后,就能以这个镜像为基础启动并运行一个容器,如果打算启动上面那个镜像的`bash`并进行交互式操作的话,要执行下面的命令
```bash
docker run -it --rm \
    ubuntu:20.04 \
    bash

root@e7009c6ce357:/# cat /etc/os-release # 简单命令
NAME="Ubuntu"
VERSION="16.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.4 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

exit # 退出容器

docker run 运行容器,具体参数如下:

  • -it 两个参数-i:交互式操作,-t:总段,打算进入bash执行一些命令并查看返回结果,因此需要交互式终端
  • --rm:是说容器退出后随之将其删除,默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动docker rm
  • ubuntu:20.04:指定这个镜像为基础来启动容器
  • bash:放在镜像后面的是命令,这里我们希望有个交互式shell,因此用的是bash

    3.2 列出镜像

    想要列出已经下载来的镜像,可以使用docker image ls命令 ```bash docker image ls docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

ubuntu 20.04 ba6acccedd29 2 months ago 72.8MB

hello-world latest feb5d9fea6a5 3 months ago 13.3kB

ubuntu 16.04 b6f507652425 3 months ago 135MB

kinesin/rstudio 1.4 8402c51aae94 8 months ago 7.08GB

包含 仓库名 标签 镜像id 创建时间 所占用的时间

<a name="yrDvK"></a>
### 3.2.1 镜像体积
docker hub显示的体积是压缩状态的,镜像在下载和上传过程中始终保持压缩状态<br />`docker images`显示的是镜像下载到本地后,展开的大小<br />另外,`docker images`列表中的镜像体积综合并非是所有镜像实际硬盘的消耗,由于docker镜像是多层存储结构,并且可以继承、服用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层,因此实际镜像硬盘占用空间很可能比列表镜像大小的总和要小<br />通过以下命令来便捷查看镜像、容器、数据卷所占用的空间
```bash
docker system df

# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          4         2         7.287GB   207.6MB (2%)
# Containers      2         1         7.322GB   0B (0%)
# Local Volumes   0         0         0B        0B
# Build Cache     0         0         0B        0B

3.2.2 虚悬镜像

docker pull可能导致虚悬镜像,docker build也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为<none>的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image),可以用下面的命令专门显示这类镜像:

docker images ls -f dangling=true

# REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
# <none>              <none>              00285df0df87        5 days ago          342 MB

一般来说,虚悬镜像已经失去了存在的价格,是可以随意删除的,可以用下面的命令删除

docker image prune

3.2.3 中间层镜像

为了加速镜像构建、重复利用资源,Docker会利用中间层镜像

# 列出中间层镜像
docker image ls -a
# 无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错

3.2.4 列出部分镜像

docker image ls ubuntu    # 根据仓库名列出镜像
docker image ls ubuntu:16.04 # 列出特定的标签 指定仓库名和标签

3.3 删除本地镜像

docker image rm [选项] <镜像1> <镜像2>

3.3.1 用ID 镜像名 摘要删除镜像

其中,**<镜像> **可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要

3.4 利用commit理解镜像构成

3.5 使用Dockfile定制镜像

镜像的定制实际上就是定制每一层所添加的配置、文件。如果可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就会解决。这个脚本就是dockfile
在空白目录中,建立一个文本文件,并命名为Dockfile

mkdir mydocker
cd mydocker
touch Dockerfile

# 内容为:
FROM Ubuntu
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM

定制镜像一定以一个镜像为基础,在其上进行定制,FROM指定基础镜像,FROM是必备的命令,并且必须是第一条指令
除了选择现有镜像为基础镜像外,Docker还存在一个特殊的镜像,名为scratch,这个镜像是虚拟的概念,并不实际存在,表示一个空白的镜像

RUN执行命令

RUN指令用来执行命令行命令的,由于命令行的强大能力,在定制镜像时是最常用的指令之一。格式有两种
shell格式RUN <命令>像直接在命令行中输入的命令一样
exec格式RUN ["可执行文件","参数1","参数2"],更像是函数调用中的格式

Dockerfile中每一个指令都会建立一层,每一个RUN的行为,都会构成新的镜像
正确写法:

FROM debian:jessie

RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

四、操作容器

4.5 导出和导入

# 导出容器
docker container ls -a

# CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES
# 7691a814370e        ubuntu:14.04        "/bin/bash"         36 hours ago        Exited (0) 21 hours ago                       test

docker export 7691a814370e > name.tar
# 导出容器快照到本地文件

# 导入容器快照
cat name.tar
docker import - test/ubuntu:v1.0

docker image ls
# REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
# test/ubuntu         v1.0                9d37a6082e97        About a minute ago   171.3 MB

注:用户既可以使用docker load来导入镜像存储文件到本地镜像库,也可以使用docker import来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息