阅读笔记Docker从入门到实践

Posted HERODING23

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阅读笔记Docker从入门到实践相关的知识,希望对你有一定的参考价值。

Docker从入门到实践

前言

Docker作为划时代性的开源项目,充分发挥了计算机虚拟化的能力,省去了虚拟机臃肿的硬件模拟,降低了开发的成本,它让应用的部署、测试、分发都变得简洁高效。本篇博客是对Docker——从入门到实践这本书的阅读与总结,主要意义还是方便自己日后查阅,当然也希望能帮助到有需要的朋友,话不多说,让我们开始吧!


1. Docker简介

1.1 什么是Docker

Docker是使用Go语言进行开发,基于Linux内核技术,对进程进行封装,属于操作系统层面的虚拟化技术。隔离的进程独立于宿主和其他隔离进程,称为容器。

1.2 Docker与虚拟机

Docker的思想类似于虚拟机,但是二者却有很大不同。传统虚拟机是虚拟一套硬件,在其上运行一个完整操作系统,再在操作系统上运行应用进程。而Docker容器中的进程直接运行在系统内核,所以轻便多。

1.3 为什么用Docker

因为相比传统虚拟化方式,Docker拥有众多优势。

  • 更高效资源利用。省去了硬件虚拟和运行操作系统的开销。
  • 更快速启动时间。直接运行在宿主内核,可以做到秒级或毫秒级,远优于传统的数分钟。
  • 一致的运行环境。Docker镜像提供除内核外完整的运行环境。
  • 持续交付和部署。Dockerfile使镜像构造透明化,利于开发和运维理解。
  • 更加轻松的迁移。环境一致性,使其在各个平台运行结果一致。
  • 更轻松维护扩展。Docker分层存储和镜像技术,重复的部分复用更容易。

对比传统虚拟机总结

2. 基本概念

Docker包括三个基本概念:镜像、容器、仓库。

2.1 镜像

操作系统分为内核和用户空间,对Linux来说,内核启动后,挂载root文件系统提供用户空间支持。而Docker镜像就相当于一个root文件系统。
Docker镜像除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

2.1.1 分层存储

Docker充分利用Union FS技术,将其设计为分层的架构。所以镜像实际由多层文件系统联合组成。镜像构建会一层层构建,前一层是后一层的基础。
分层的特征使得镜像的复用、定制更为容易,甚至可以根据之前定义好的镜像为基础层,进一步添加层,构建新的镜像。

2.2 容器

镜像与容器,就像类与对象的关系。镜像是静态的定义,容器是镜像运行的实体。
容器的实质是进程,但运行时有自己独立的命名空间
每个容器运行,是以镜像为基础层,在其上创建一个当前容器的存储层,称为容器存储层。容器消亡,容器存储层也随之消亡。
容器存储层要保持无状态化,容器不能向其写入任何数据。所有文件写入操作,使用数据卷,或者绑定宿主目录,在这些位置上读写直接跳过容器存储层,直接对宿主读写,性能和稳定性高。
数据卷的生存周期独立于容器,容器消亡,数据不会丢失。

2.3 仓库

Docker Registry提供集中存储、分发镜像的服务。一个Docker Registry包含多个仓库,每个仓库包含多个标签,每个标签对应一个镜像。
通常,一个仓库包含同一个软件不同的版本镜像,标签对应软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
仓库名的形式: 两端路径,如 heroding/fate,前者代表Registry多用户环境下的用户名,后者代表对应的软件名(不绝对,取决于具体的服务)。

2.3.1 Docker Registry 公开服务

这是开放给用户使用、允许用户管理镜像的Registry服务。这类公开服务允许用户免费上传、下载公开的镜像。
最常用的Registry公开服务是官方的Docker Hub,这也是默认的Registry,拥有大量官方镜像

2.3.2 私有Docker Registry

用户可以在本地搭建私有的Docker Registry。Docker官方提供了Docker Registry镜像,可以直接使用作为私有的Docker Registry服务。
开源的Docker Registry只提供了Docker Registry API服务端实现,足以支持docker命令,不包括图形化界面、维护、用户管理等高级功能。
除了官方的Docker Registry,第三方软件也实现了Docker Registry API,甚至提供了用户界面及一些高级功能,如HarborSonatype Nexus

3. Ubuntu安装Docker

由于博主搭建的Linux系统为Ubuntu,所以这里仅介绍Ubuntu安装Docker的步骤。
Docker支持以下Ubuntu版本:

  • Ubuntu Hirsute 21.04
  • Ubuntu Groovy 20.10
  • Ubuntu Focal 20.04 (LTS)
  • Ubuntu Bionic 18.04 (LTS)

3.1 卸载旧版本

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

当然如果版本不匹配,进行卸载时,有如下步骤。

# 删除软件和安装时自动安装的包
$ sudo apt-get autoremove docker docker-ce docker-engine  docker.io  containerd runc

# 删除相关配置文件
$ dpkg -l | grep docker
$ dpkg -l |grep ^rc|awk 'print $2' |sudo xargs dpkg -P

# 卸载docker相关插件
$ sudo apt-get autoremove docker-ce-*

# 删除docker目录
$ sudo rm -rf /etc/systemd/system/docker.service.d
$ sudo rm -rf /var/lib/docker

# 确定docker卸载完毕
$ docker --version

3.2 使用APT安装

这里先给出官网的安装步骤。

  1. 设置存储库。

更新apt包索引并安装包以允许apt通过 HTTPS 使用存储库。

 $ sudo apt-get update
 $ sudo apt-get install \\
    ca-certificates \\
    curl \\
    gnupg \\
    lsb-release

添加 Docker 的官方 GPG 密钥。

 $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

设置稳定存储库。

$ echo \\
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \\
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  1. 安装Docker引擎

更新apt包,安装最新版本的Docker Engine和containerd。

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

安装特定版本的Docker Engine,列出版本,选择安装。

$ apt-cache madison docker-ce
$ sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io

验证安装是否正确。

$ sudo docker run hello-world
  1. 升级Docker引擎
$ sudo apt-get update

剩下的步骤从步骤2安装特定版本Docker Engine开始。

3.3 使用Docker

3.3.1 启动Docker

使用Docker前要启动Docker,并让其开机自启。

$ sudo systemctl enable docker
$ sudo systemctl start docker

3.3.2 建立Docker用户组

默认情况下,docker使用Unix socket与Docker引擎通讯。出于安全考虑,只有root用户和docker组的用户才可以访问Docker引擎的Unix socket。更好的做法是将使用docker用户加入到用户组中。

$ sudo groupadd docker
$ sudo usermod -aG docker $USER

3.3.3 测试Docker安装是否正确

$ docker run --rm hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

输出如上信息,则说明安装成功。

4. 使用镜像

4.1 常用Docker命令

一些常用的Docker命令,便于查阅。

$ docker images # 显示镜像
$ docker ps -a #查看当前系统中容器的列表。
$ docker ps -l #会列出最后一次运行的容器,包括正在运行和已经停止的。
$ docker start  #启动一个或多个已经被停止的容器
$ docker stop  #停止一个运行中的容器
$ docker rm #删除一个或多个容器
$ docker exec #在运行的容器中执行命令
$ docker restart #重启容器
$ docker stop [容器名称/容器ID] #停止容器运行
$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] #获取镜像
$ docker run -it --rm xxx bash #镜像启动容器

4.2 获取镜像

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

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

选项包括-a和-p,具体可以通过docker pull --help命令查看。
镜像名称格式:

  • Docker镜像仓库地址:格式为<域名/IP>[:端口号],默认地址是Docker Hub(docker.io)。
  • 仓库名:两段式,<用户名>/<软件名>。对于Docker Hub,不给用户名,默认library,即官方镜像。

4.3 运行

有了镜像,就可以以这个镜像为基础启动并运行容器。

$ docker run -it --rm xxx bash

参数说明:

  • -it:这是两个参数,-t交互式操作,-t终端,即需要交互式终端执行命令,查看结果。
  • --rm:容器退出后即删除,避免浪费空间。
  • xxx:指定镜像。
  • bash:用bash作为交互式shell。

4.4 列出镜像

$ docker system df #查看镜像、容器、数据卷所占空间
$ docker image ls -a #显示所有镜像(包括中间层镜像)
$ docker image ls #列出所有顶层镜像
$ docker image ls xxx #列出特定的某个镜像
$ docker image ls -f since=mongo:3.2 #过滤镜像(显示之后的)
$ docker image ls -f before=mongo:3.2 #过滤镜像(显示之前的)
$ docker image ls -f label=com.example.version=0.1 #用label过滤
$ docker image ls -q #以特定的格式显示(显示所有镜像ID)

# 通过go的模板语法列出镜像结果
$ docker image ls --format ".ID: .Repository" #只包含镜像ID和仓库名
$ docker image ls --format "table .ID\\t.Repository\\t.Tag" #以表格等距显示,并且有标题行

4.5 删除镜像

$ docker image rm [选项] <镜像1> [<镜像2> ...]  #删除可以是长ID也能是短ID
$ docker image rm 501 #根据短ID
$ docker image rm centos #根据名字

删除行为分为两类,一类是Untagged,另一类Deleted。镜像唯一标识是ID和摘要,而一个镜像可以有多个标签。所以删除的时候,首先将所有标签都取消掉(即Untagged),如果有别的标签指向了这个镜像,那么Delete行为就不会发生。所以并不是所有rm操作都会删除镜像,可能只是取消某个标签而已。
先删除容器,再删除镜像(容器是以镜像为基础的)。

$ $ docker image rm $(docker image ls -q redis) #删除所有仓库名为redis的镜像
$ $ docker image rm $(docker image ls -q -f before=mongo:3.2) #删除所有在 mongo:3.2 之前的镜像

4.6 镜像构成

以定制一个Web服务器为例。

$ docker run --name webserver -d -p 80:80 nginx

这条命令用Nginx镜像启动一个容器,命名为webserver,映射了80端口。
访问结果如上图所示,如果想修改成欢迎Docker的文字,可以使用docker exec命令进入容器修改。

$ docker exec -it webserver bash
root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit
exit

以交互终端方式进入webserver,执行bash获得可操作的Shell。

$ docker diff webserver #查看具体的改动
$ docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] #将修改内容保存为镜像

# 举例
$ docker commit \\
    --author "Tao Wang <twang2218@gmail.com>" \\
    --message "修改了默认网页" \\
    webserver \\
    nginx:v2
sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214

$ docker history #具体查看镜像内的历史记录

慎用docker commit!
相当于黑箱操作,维护非常困难且痛苦。

参考链接

https://www.cnblogs.com/shmily3929/p/12085163.html
https://docs.docker.com/engine/install/ubuntu/
https://www.docker.com/
https://yeasy.gitbook.io/docker_practice/

以上是关于阅读笔记Docker从入门到实践的主要内容,如果未能解决你的问题,请参考以下文章

Docker 从入门到实践系列三 - Docker 常用命令

Docker 从入门到实践系列三 - Docker 常用命令

我的Docker学习笔记:从入门到实战过程全记录

我的Docker学习笔记:从入门到实战过程全记录

Docker快速入门

Docker入门到实践——简单操作