云计算时代,你还不会 Docker?史上最全 Docker 教程

前言

大家好,我是林哥!

林哥,双一流研究生,研究生毕业斩获美团、有赞、同花顺、哔哩哔哩、大华等多家大厂 offer,现互联网大厂大数据工程师,深耕于大数据实时计算领域。

2021年以来,云原生、云计算时代的趋势已经在渐渐的铺开了,这些都与 Dokcer + K8S 两个技术的盛行分不开。

今天。林哥给大家总结一波 Docker 学习笔记!其中包含以下几个方面:
思维导图,关注公众号,小林玩大数据,回复【Docker】,即可获取!
在这里插入图片描述

1.什么是 Docker?

在给大家介绍什么是 Docker 前,先给大家讲讲为什么会有 docker 出现?

为什么会有 Docker?

一款产 品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验, Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。

环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装? 也就是说,安装的时候,把原始环境-模-样地复制过来。开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。

什么是 Docker ?

Docker是基于Go语言实现的云开源项目。官方对 Docker 的介绍是,一次封装,到处运行。这样便解决了运维与开发之间环境不一致等问题。

总之,Docker 解决了运行环境和配置问题的一种容器,方便做持续集成并有助于整体发布的容器虚拟化技术。

Docker 能干嘛?

Docker 是一种资源虚拟化技术,开发可以将产品所用到的依赖放到一个可移植的容器中,就可以发布到任何流行的 Linux 上。Docker 虽然是一种虚拟化技术,但和我们常说的虚拟机又有不同:

  • 虚拟机是一台物理机,虚拟出多个虚拟机实例,模拟了一个完整的操作系统;

    微信图片_20211219133137
  • Docker 容器则是一台物理机上启动多个容器实例,仅仅对进程进行隔离,系统与宿主机共享。不会模拟整个操作系统,只包含软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

    微信图片_20211219133144

虚拟机与 Docker对比:

在这里插入图片描述

容器之间进程不会相互影响,也能区分计算资源!

2.Docker 安装

在讲 Docker 安装前,需要正确的理解**仓库/镜像/容器 **这几个概念:

  • 镜像: 跨平台、可移植的程序+环境包
  • 容器:依据镜像所生成的容器实例,进行了资源隔离的运行时环境。
  • 仓库:存放镜像的地方,类似 GitHub ,代码仓库。

本文基于 CentOs 7 安装 Docker

如果有小伙伴是 6.8 或其它版本,可能需要稍作调整。林哥是自己购买了阿里云的云服务器,各位小伙伴可以在虚拟机中实操。

官网官方文档:https://www.docker.com/

首先,检查下自己的版本是否是 CentOs 7 版本:

cat /etc/centos-release

在这里插入图片描述

如果显示版本是7.0及以上,本文教程适合。

因为版本不一样,安装过程有点不一样,至于其它 CentOs 版本,林哥把整理好的安装教程,放在了思维导图中,公众号后台回复 【Docker】即可获取

1.yum 安装 gcc 相关:

yum  -y install gcc
yum -y install gcc-c++

2.安装Docker 的依赖库:

yum install -y yum-utils device-mapper-persistent-data lvm2

3.添加Docker CE的软件源信息(推荐设置阿里云):

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

4.安装 Docker CE

yum makecache fast
yum -y install docker-ce

5.启动 Docker

systemctl start docker

经过以上 5 大步骤就已经把 Docker 安装好了,是不是很简单!

但是,还没完,一个最重要的步骤,配置镜像仓库,这里林哥给大家推荐阿里云镜像仓库。否则,Docker 默认采用的是官方的镜像仓库,访问简直龟速!

阿里云镜像加速器地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

阿里云为每个账户都设置了一个专属的镜像加速地址,大家只要在阿里云注册账户,就可以了(不得不说阿里真的有钱)。

6.配置Docker 自定义镜像仓库地址。

mkdir -p /etc/docker
vim /etc/docker/daemon.json
#输入以下地址
{  "registry-mirrors": ["https://{自已的编码}.mirror.aliyuncs.com"]}

当然你也可以一步到位

tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://{自己的编码}}.mirror.aliyuncs.com"]
}
EOF

7.重新加载服务配置文件

systemctl daemon-reload

8.重启 Docker 服务及测试

systemctl restart docker
docker version

如果出现下面两个版本,说明安装成功。

在这里插入图片描述

永远的 HelloWorld

相信任何一个程序员都熟悉 HelloWorld 这个案例,Docker 也不例外,拥有自己的 HellowWorld 案例。林哥带大家跑一跑案例:

1.首先从镜像仓库上拉取一个 hello-world 镜像

#远程拉取镜像
docker pull hello-world
#查看本地镜像
docker images

2.运行 hellow-world

docker run hellow-world

image-20211211225452451

大家可能会好奇,docker run,这其中做了什么?

当在宿主机运行 Docker,通过docker rundocker start创建新容器进程时,会传入Linux 的 CLONE_NEWPID 命名空间,实现进程上的隔离。注意:命名空间是 Linux 用于分离进程树、网络接口、挂载点以及进程间通信等资源的手段。Linux 提供了七种不同的命名空间,命名空间不同,新进程所要与宿主机隔离的资源也不同。其中,Docker 启动时,使用的就是 CLONE_NEWPID 。

Docker 是如何工作的?

Docker是一个 Client-Server 结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。

为什么 Docker 比 VM 快?

  1. docker 有着比虚拟机更少的抽象层。由亍 docker 不需要Hypervisor实现硬件资源虚拟化, 运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
  2. docker利用的是宿主机的内核,而不需要Cent OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。避免引寻、加载操作系统内核等比较费时、资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Cenet OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。

3.Docker 常用命令

在日常工作中,掌握林哥在这里所列出命令,便足以应付日常工作。如果你要往 Docker 运维工程师发展,那还需要深入学习,林哥也给大家推荐一本书:《Docker 核心技术与实现原理》。

3.1帮助命令

docker version

这个命令可以获取 Docker 的客户端和服务端的版本号,一般用于测试 Docker 的安装以及校验版本的兼容性。

docker info

这个命令是用于显示 Docker 系统信息,包括镜像和容器数,其中也包括我们上面设置的阿里云镜像加速。

image-20211212004147563
在这里插入图片描述

docker --help

这个可以算是殿堂级的命令,类似于 Linux 的 man 命令。直接执行docker --help,可以显示 docker 最全的命令集,并配有详细的解释。但是它还有另外一种用法,可以查看具体命令的详细用法,以及相应参数所表示的含义。例如:

docker  exec  --help

在这里插入图片描述

其中最常用的是 -i -t,-i:表示交互模式打开容器 -t:返回一个伪终端。

因此,可以通过 docker ps | grep name,找到相应的容器 ID ,然后通过 exec 命令对指定的容器执行 bash:

docker exec -it 容器ID /bin/bash

如果对于其它命令不是很熟,便可使用 docker 命令 --help 查看其详细用法。

3.2镜像命令

docker images

用于列出本地主机上所有的镜像。

各个选项说明:

  • REPOSITORY:表示镜像的仓库源

  • TAG:镜像的标签

  • IMAGE ID:镜像ID

  • CREATED:镜像创建时间

  • SIZE:镜像大小

    同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像

命令参数:

-a :列出本地所有的镜像(含中间映像层)
-q :只显示镜像ID
--digests :显示镜像的摘要信息
--no-trunc :显示完整的镜像信息

docker search imageName

该命令用于搜索镜像。

网站:https://hub.docker.com

参数说明:

#用法
docker search [OPTIONS] 镜像名字
#参数
--no-trunc : 显示完整的镜像描述
-s : 列出收藏数不小于指定值的镜像
--automated : 只列出 automated build类型的镜像

docker pull imageName

用于到配置的镜像仓库下载镜像。

该命令先使用 docker search, 然后使用 docker pull 镜像名字:TAG,下载即可。

docker rmi imageName

用于删除本地某个镜像,分三种情况:

  1. 删除单个镜像:docker rmi -f 镜像ID

  2. 删除多个镜像:docker rmi -f 镜像名1:TAG 镜像名2:TAG

  3. 删除所有镜像:docker rmi -f $(docker images -qa)

    -f :表示强制删除

3.3容器命令

前文说了,容器是根据镜像创建的实例。因此,要创建容器,必须要有镜像。

新建并启动容器

语法docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

参数说明:

 #OPTIONS说明(常用):有些是一个减号,有些是两个减号 
 --name="容器新名字": 为容器指定一个名称
 -d: 后台运行容器,并返回容器ID,也即启动守护式容器
 -i:以交互模式运行容器,通常与 -t 同时使用
 -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
 -P: 随机端口映射;-p: 指定端口映射,有以下四种格式      
 ip:hostPort:containerPort  ip::containerPort  hostPort:containerPort  containerPort

实例:

启动交互式容器:

#使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
docker run -it centos /bin/bash  

列出当前所有正在运行的容器

语法docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

参数说明:

#OPTIONS说明(常用): 
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器
-n:显示最近n个创建的容器
-q :静默模式,只显示容器编号
--no-trunc :不截断输出。

退出容器

两种退出方式:

  1. 容器停止并退出:exit
  2. 容器不停止退出:ctrl+P+Q

启动容器

命令:docker start 容器ID或容器名

重启容器

命令:docker restart 容器ID或者容器名

停止容器

命令:docker stop 容器ID或者容器名

强制停止:docker kill 容器ID或者容器名

删除已停止容器

l两种方式:

  1. 删除多个容器:docker rm -f $(docker ps -a -q)
  2. 删除多个容器:docker ps -a -q | xargs docker rm

几个重要命令

上文讲了几个容器基本的命令,接下来聊一聊几个日常工作中非常重要的一些命令。

启动守护式容器docker run -d 容器名

使用镜像 centos:latest 以后台模式启动一个容器 docker run -d centos

问题:然后docker ps -a 进行查看, 会发现容器已经退出。

很重要的要说明的一点: Docker 容器后台运行, 就必须有一个前台进程.

容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。 这个是docker的机制问题。

例如:你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start,但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀,因为他觉得他没事可做了.所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行

查看容器日志: docker logs -f -t --tail 容器ID

参数说明:

  -t 是加入时间戳\
  -f 跟随最新的日志打印
  --tail 数字 显示最后多少条

查看容器内部细节docker inspect 容器ID

进入正在运行的容器并以命令行交互,有两种方式:

  • docker exec -it 容器ID /bash/Shell
  • 重新进入:docker attach 容器ID

区别:

  • attach 直接进入容器启动命令的终端,不会启动新的进程

  • exec 是在容器中打开新的终端,并且可以启动新的进程

从容器内拷贝文件到主机上docker cp 容器ID:容器内路径 目的主机路径

4.Docker 镜像

镜像的本质?

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。

Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录.

Docker 镜像的加载原理

Docker镜像加载原理: docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称之为 UnionFS。

bootfs(boot file system) 主要包含 bootloader 和 kernel, bootloader 主要是引导加载 kernel, Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。

rootfs (root file system) ,在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等等 。

平时我们安装进虚拟机的 CentOS 都是好几个G,为什么docker这里才200M?对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs 基本是一致的, rootfs会有差别, 因此不同的发行版可以公用 bootfs。

Docker 镜像特点

当镜像被命令创建时就会在镜像的最上层添加一个可写的层,也就是容器层,所有对于运行时容器的修改其实都是对这个容器读写层的修改。容器和镜像的区别就在于,所有的镜像都是只读的,而每一个容器其实等于镜像加上一个可读写的层,也就是同一个镜像可以对应多个容器。

为什么 Docker 要采用分层结构?

最大的一个好处就是-共享资源 比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份 base 镜像, 同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称为容器层,容器层之下都叫镜像层

镜像制作案例

本小节通过一个案例,来演示 docker commit 操作。你可以简单的类比 git commit命令。

docker commit:提交容器副本使之称为一个新的镜像,其最常用的命令:

docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

本文使用 tomcat 作为 base 镜像,通过简单的删除文档,然后将新的镜像提交,使之称为一个没有文档的新镜像。

1.先从配置好的镜像仓库拉取一个 tomcat 镜像到本地,并成功运行

docker pull tomcat
docker run -it -d -p 8080:8080 tomcat

#参数解释
-p主机端口:docker容器端口
-P:随机分配端口
i:交互
t:返回一个伪终端

2.进入容器,并故意删除上一步镜像所产生 tomcat 容器的文档

docker exec -it 容器id /bin/bash
#删除文档

  1. 当前 tomcat 运行的容器实例是一个没有文档内容的容器,以他为模板 commit 一个没有文档的 tomcat 新镜像:tomcat01

  2. 启动新镜像并和原来的对比,验证。

上述只是一个简单制作新镜像的流程,大家可以通过这个流程,大致了解制作镜像,需要做哪些,其中最重要的是,dockerfile 文件的编写,在第 6 小节会介绍。

5.Docker 容器数据卷

什么叫数据卷?

简单来说,容器数据卷有点类似我们 Redis 里面的 rdb 和 aof 文件,主要用于做容器的持久化,以及容器间继承、容器与宿主机共享数据。

如何添加数据卷?

  1. 直接命令添加

    命令: docker run -it -v /宿主机目录:/容器内目录 centos /bin/bash

    启动一个 centos 容器,并把宿主机的目录与容器内的目录做一个绑定,这样即使容器退出或停止,其产生的数据仍然存储在主机上,不会被清除。

  2. 使用 DockerFile 添加

    到现在为止,还没介绍 DockerFile ,大家先试着理解一下。

    可在 Dockerfile 中使用 VOLUME 指令来给镜像添加一个或多个数据卷

    VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"] 
    

    说明: 出于可移植和分享的考虑,用 -v 主机目录:容器目录,这种方法不能够直接在 Dockerfile 中实现。由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。

    DockerFile 构建:

     # volume test
     FROM centos
     VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
     CMD echo "finished,--------success1"
     CMD /bin/bash 
    

    根据上述 DockerFile ,使用 docker build (类似于 Maven build)构建一个新的 centos 镜像,这个镜像添加了多个数据卷。

什么叫数据卷容器?

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

6.DockerFile 解析

什么是 dockerfile?

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。使用 DockerFile 构建一个新的镜像有 3 个步骤:

  1. 编写 DockerFile 文件
  2. 根据 DockerFile 文件,使用 docker build 构建镜像
  3. docker run 启动一个容器实例

dockerfile 构建过程

dockerfile 文件中的指令都必须为大写字母,且后面要跟上一个或多个参数;执行流程从上到下按照顺序执行,每条指令都会创建一个新的镜像层,并对镜像进行提交。其执行流程如下:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

总之,从应用软件的角度来看,Dockerfile、Docker镜像与 Docker 容器分别代表软件的三个不同阶段。Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,Docker 容器则可以认为是软件的运行态。Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

1.Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;

3 Docker容器,容器是直接提供服务的。

docker 指令

docker 指令用于编写 dockerfile 文件,通过指令可以自定义特定功能的镜像。

  • FROM:基础镜像,解释:表明当前新镜像是基于哪个镜像生成的

  • MAINTAINER:镜像维护者的姓名和邮箱地址

  • RUN:容器构建时需要运行的命令

  • EXPOSE:设置当前容器对外暴露出的端口

  • WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点

  • ENV:用来在构建镜像过程中设置环境变量

    ENV MY_PATH /usr/mytest ,这个环境变量可以在后续的任何 RUN 指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量, 比如:WORKDIR $MY_PATH

  • ADD:将宿主机目录下的文件拷贝进镜像且 ADD 命令会自动处理 URL 和解压 tar 压缩包

  • COPY:类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

    例如:COPY src dest

  • VOLUME:容器数据卷,用于数据保存和持久化工作,第 5 小节详细介绍过。

  • CMD :指定一个容器启动时要运行的命令

    注意:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换

  • ENTRYPOINT ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数

  • ONBUILD:当构建一个被继承的 Dockerfile 时运行命令,父镜像在被子镜像继承后,父镜像的onbuild被触发

案例实操

Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件所构建出来的。这个过程,就需要我们去编写 dockerfile 文件。下面,通过自定义一个 mycentos 镜像和自定义 tomcat 镜像,解释 dockerfile 编写。

自定义 mycentos 镜像具备如下功能:

  • 登陆后的默认路径

  • 具备 vim 编辑器

  • 查看网络配置 ifconfig 支持

编写 dockerfile 文件

FROM centos
MAINTAINER lin<linge@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATHRUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash  

构建

docker build -t 新镜像名字:TAG .

运行

docker run -it 新镜像名字:TAG

验证

#进入容器
docker exec -it 容器ID /bin/bash
#输入命令 vim ifconfig 验证

这样,我们就构建了一个新的镜像,并且支持 vim/ifconfig 命令,镜像扩展成功。

林哥,双一流研究生,研究生毕业斩获美团、有赞、同花顺、哔哩哔哩、大华等多家大厂 offer,现互联网大厂大数据工程师,深耕于大数据实时计算领域。

好了,今天的文章到这里,更文不易,点个在看吧!
为了方便阅读,本文已经制作成 pdf 版本,关注公众号,回复:【0】即可获取

微信扫码订阅
UP更新不错过~
关注
  • 3
    点赞
  • 4
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

小林玩大数据

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值