Docker入门笔记
2023-1-12
| 2025-11-26
Words 6490Read Time 17 min
URL
type
status
date
slug
summary
tags
category
icon
password
notion image
docker能够帮助我们快速部署项目而不用考虑环境搭建问题
👨🏻‍💻更新至:发布镜像

docker的作用

发布项目时,将环境一起打包,做成一个镜像。
然后可以把镜像上传到Docker仓库(类似npm),其他人就可以下载直接部署,不用考虑环境配置问题
  • 容器技术: 容器技术就是一种轻量的虚拟化技术。虚拟机可以模拟物理机,让一台物理机上运行多个系统,我们可以下载一个装好所有环境的系统镜像到虚拟机里直接运行。但是虚拟机十分笨重,动辄占用几个g的空间,内容占用也不小。因此有一群人想做一款轻量级的虚拟机——LXC(Linux Container), 相比传统的虚拟化技术,它与宿主机共用一个内核,性能损耗小,不需要指令级模拟,不需要即时编译,容器可以在CPU核心的本地运行指令,避免了准虚拟化和系统调用替换中的复杂性,轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享,总之就是只保留最核心的那点功能。虚拟机可能需要几个g,但是Docker只要几mb。而Docker的底层就是用LXC实现的,LXC将linux进程沙盒化,使得进程之间相互隔离,并且能对各进程资源合理分配。
  • Docker和虚拟机的区别 从上图可以看出,传统的虚拟机,每运行一个应用就得有一个完整的系统支撑(一个系统跑多个应用可能不稳定不安全,因此要隔离),每个系统都跑自己的内核,虚拟机还得模拟一整套的硬件出来,性能消耗极高,抽象层也巨多。而docker将每个应用隔离起来,由dockers管理程序直接使用宿主机的内核,多个应用共享一个内核,大大降低了负担,充分发挥宿主机的性能。虚拟机是一个人给他盖一栋楼办公,而docker是给所有人盖一栋楼办公,一人给一个独立小房间。
  • Docker的作用
      1. 第一个就是开头说的,更方便的部署项目,不用考虑环境的搭建
      1. 第二个就是让一个服务器跑多个容器实例,充分压榨服务器性能

Docker工作过程简述

notion image
img
如上图:
  • image:镜像,用于创建docker容器的模板。
  • container:容器,镜像运行时的实例,用虚拟机类比:镜像就是一个系统的iso镜像,而容器就是用这个镜像跑起来的一个个系统。
  • Registry:docker资料库,一个registry可以包含多个仓库repository,而一个仓库包含多个标签,每个标签对应一个镜像。而这个registry的概念和git仓库的概念差不多,我们可以建立私有的registry,也可以用官方的docker hub

安装docker

本文使用cenOS 7系统。
1. 查看Linux系统内核版本是否符合
输入命令
,最好3.10以上
notion image
或者输入 # cat /etc/os-release ,查看版本发布信息。不同系统可以在官方文档查看安装要求
2.卸载旧版本
输入命令卸载旧版本
3.下载yum工具包
4.用yum添加docker仓库
5.更新yum索引
6.安装docker
7.启动docker
8.判断docker是否启动成功
到这里就已经成功安装docker了,下面用一个hello world示例来初步体验一下。
9.Hello World!
notion image
image-20230111192720918
再次运行命令 docker run hello-world 即可成功运行。 10.查看拉取的镜像
notion image
image-20230111192946407
11.卸载docker

Docker常用命令

帮助命令

命令
作用
docker version
显示版本信息
docker info
显示系统信息,包括容器和镜像数量
docker 命令 --help
命令帮助信息

镜像命令

docker image : 列出本地镜像信息

名词解释:
  • REPOSITORY:镜像的仓库源
  • TAG :镜像的标签
  • IMAGE ID:镜像的id
  • CREATED:镜像创建时间
  • SIZE:镜像大小
可选项:
  • a :列出所有镜像
  • q :只显示id
  • 通常两个连用,显示所有镜像id docker images -aq

docker search 镜像名称:搜索docker hub 上的镜像

和在DockerHub搜索一样
可选项:
  • filter:过滤,比如 dockers search --filter=stars=4000 搜索stars不少于4000的镜像

docker pull 远程镜像名称 :下载镜像

注:docker pull imge_name:tag 可以指定tag,tag通常用于标记版本,tag默认为latest即最新版本。

docker rmi 镜像id/镜像名称:删除指定镜像

docker tag 给镜像打标签

打了tag后会生成一个新镜像

容器命令

docker run:新建容器并启动

docker run 命令以镜像为模板创建一个容器,并且运行容器
-p选项暴露端口,因为访问请求先要通过宿主机的端口,再通过容器的端口,因此 -p 主机端口:容器端口 可以把宿主机的端口和容器的端口打通,建立一个映射。比如 docker run -p 3080:8080 某镜像,就可以让请求先访问宿主机的3080端口,再访问容器的8080端口。

docker ps:查看运行的容器

docker ps 类似linux命令中的ps进程查看命令,可以查看运行中或曾经运行过的容器的信息。

退出容器

注:容器退出后并不会被删除,用docker ps -a 查看所有存在的容器

删除容器

启动和停止容器

其他命令

查看日志

查看容器中的进程信息

查看容器的元数据

进入容器

前面说过,docker类似一种极简虚拟机,所以一个容器就相当于一个正在运行的linux系统,我们进入这个容器就是进入这个系统。

主机和容器间的文件拷贝

性能监控

命令图示

notion image
img

Docker镜像的原理

bootfs和rootfs

fs即file system 文件系统,Linux系统的文件系统由bootfs和rootfs组成
  • bootfs:包含bootloader和kernel,bootLoader用于引导内核kernel,你等待电脑开机的那段时间就首先调用了bootLoader然后引导内核加载进内存,bootloader就被卸载释放内存。
  • rootfs:包含典型的目录结构,包括/dev, /proc, /bin, /etc, /lib, /usr, and /tmp等,还有运行应用所需要的各种文件。用户可以对这个文件进行修改,Linux 系统在启动时,roofs 首先会被挂载为只读模式,然后在启动完成后被修改为读写模式,随后它们就可以被修改了。
bootfs在众多linux发行版中都大致一样,而rootfs在不同的发行版中通常不同,比如ubuntu和centos

UnionFS(Union File System)联合文件系统

UnionFS(联合文件系统)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,可以把多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的,并且允许可读和可写目录并存。也就是说unionfs可以把多个文件系统联合成一个单一的文件系统,这个联合起来的新文件系统可以对其中任意的文件进行操作,但其实并没有改变原来的文件,因为这里使用了写时复制技术。
写时复制(copy-on-write简称CoW):也叫隐式共享,是一种对可修改资源实现高效复制的资源管理技术。它的思想是,如果一个资源是重复的,但没有任何修改,这时候并不需要立即创建一个新的资源;这个资源可以被新旧实例共享。创建新资源发生在第一次写操作,也就是对资源进行修改的时候。通过这种资源共享的方式,可以显著地减少未修改资源复制带来的消耗,但是也会在进行资源修改的时候增减小部分的开销。
我们用docker pull 命令下载镜像时看到的分层下载的方式就是基于这个系统。

UnionFS在Docker镜像中的使用

Docker镜像的设计中引入了层(layer)的概念,对镜像的每一步修改,都会生成一个层,一个层也就是一个文件系统,而UnionFS就把这所有的文件系统目录联合起来生成一个单一的根目录。
notion image
image-20230112214225531
最底层的内核就是用的宿主机的,因为不同发行版本linux的bootfs都是一样的。
我们可以发现docker中的centos镜像就两百兆,因为它主要只包含了rootfs部分,其它都用的宿主机的。
一个应用的运行,需要许多的依赖,比如Tomcat需要jdk,而其它应用也需要jdk,因此jdk就可以单独一层,而其它需要jdk的应用都共用这一个jdk,它们本身的层建立在这个jdk层之上。而这个jdk也也是一个镜像,也就是说,一个镜像需要一系列基础的镜像,而基础的镜像时可以重复利用的。
当我们下载一个镜像时,会先寻找本地有没有基础镜像,如果有基础镜像就只下载没有的层。
notion image
image-20230112220450283
容器运行时:我们说过镜像是一个模板,需要用它来创建容器,容器才是实实在在运行的实例。这时有几个个疑问:容器是拷贝整个镜像到内存然后运行吗?这样未免太浪费内存,实际上容器都基于同一个镜像运行,那如果有多个容器,其中一个对文件进行了改动,会影响其他容器吗?
这就体现了uninFS的强大之处了,镜像通常都是只读的。在运行容器时,最上面会新建一个可以读写的容器层,而我们对文件的所有修改都存在这个新的层中,也就是运用了unionFS的写时复制技术。所以对容器的改变不会影响镜像(如上图)
容器

Commit镜像

一个例子

下面通过一个实例来演示一个镜像的制作过程
  1. 首先得有一个基础镜像,下载一个tomcat镜像并运行一个容器(tomcat是一个轻量级应用服务器,可以在上面运行一个网站)
    1. 你会发现网站是404,因为官方tomcat镜像并不完整,我们需要把tomcat目录下面的webapps.dist目录内的内容全部复制到webapps目录里,相当于本来有个默认网页,但是必须放在webapp文件夹里才能访问
      1. 再访问 ipddress:8080 就能看到网页显示了
    1. 刚才我们对这个容器的文件进行了修改,这些修改并不会影响基础镜像tomcat,而是在最上面的可读写的容器层进行的。现在,我们可以把这多加的一层也打包进镜像里,成为一个能直接运行默认网页的镜像。也就是说这个容器可以变成一个镜像!

    docker commit

    利用这个命令将上面例子中的容器变为镜像
    如下图我们可以看到返回了一个镜像id,然后镜像列表里也多了tomcatpro
    notion image
    image-20230112231509281
    由此可以看出,镜像是由一些一开始就有的基础镜像,然后在容器层中修改,打包成新镜像,然后又有人以新镜像为基础,又添加新的层变成另一个镜像,这样一层一层的添加就成了如今众多的docker镜像。
    目前我们的镜像还在本地,之后再学习如何上传到docker hub和全世界的coder分享。

    容器数据卷

    基本使用

    问题引导:我们运行了一个容器,它在运行时会产生很多数据,但是数据都存在容器里,一旦容器删除,数据就丢失了。还有就是我们想让本地的数据传输进容器,要是每次都必须手动docker cp,就会十分麻烦。所有我们需要一种方法,将容器的数据和本地的数据同步起来。
    卷技术数据卷就是宿主机上的一个可供容器使用的目录。可以将容器内的目录挂在到宿主机上(类似虚拟机中linux和本地Windows的共享文件夹)。这样容器内的目录和宿主机上的目录形成映射,共享同一个目录(同一个物理地址),并且也支持容器与容器之间共享。
    使用 docker run -v 主机目录:容器目录 可以在容器目录上挂载一个主机目录,当容器删除时,数据还保留在宿主机中。
    当主机中文件发生变动,容器中也会同步,反之容器目录变动主机也会同步(本质上是一个物理数据),形成双向的连接。甚至同一个数据卷可以挂载到多个容器上
    notion image
    image-20230114212335253

    具名挂载和匿名挂载与docker volume命令

    匿名挂载
    直接使用 -v 容器内路径 ,只指定容器内路径,不指定容器外路径,可以实现匿名挂载
    docker volume ls 可以查看数据卷列表信息
    notion image
    可见,匿名挂载后,系统会为该数据卷随机分配一个名字。
    具名挂载
    • v 数据卷名字:容器内路径 冒号前如果是斜杠开头/xxx 就是主机路径,如果只写一个单词就是指定数据卷名字,这样就能自己为数据卷分配一个名字。
    可以看到数据卷更详细的信息。
    notion image
    可见,如果没有指定主机目录的位置,那么数据卷默认在
    /var/lib/docker/volumes/
    目录下。
    具名挂载能更方便的找到卷的位置,因此常用具名挂载
    权限问题
    • v 容器路径:ro/rw 可以指定卷的权限

    数据卷容器

    docker run --volume-from 父容器名 将容器挂载到父容器上,父容器也叫数据卷容器。 数据卷容器是挂载了数据卷的容器,卷目录是映射到宿主机上的,而--volume-from 命令告诉子容器也要挂载到这个或这些卷上,类似一种继承关系。因此子容器也是挂载到宿主机上的,当数据卷容器被停止或删除,并不影响子容器继续挂载宿主机上对应的卷。

    DockerFile

    DockerFile是一种脚本文件,用来构建镜像。而前面说过镜像是一种层级结构,因此针对每一层就可以用特定指令规定怎么创建。

    指令

    dockerfile文件中会写许多脚本指令,有如下特点:
    • 关键字大写(规范)
    • 从上到下顺序执行
    • 注释用 # 开头
    写好Dockerfile脚本后,用docker build 命令创建镜像

    实战

    docker histroy 镜像id 可以查看镜像的是如何用指令一步步构建的

    易混指令

    ADD和COPY

    两者都是把本地文件拷贝到镜像中,没有指定路径默认在上下文目录中寻找
    • ADD除了能做到这个,还能
      • 通过url下载文件
      • 将解压压缩文件添加到镜像中

    RUN,CMD和ENTRYPOINT

    三者都是指定一个命令执行,但是如下区别
    RUN:
    • RUN是在镜像的构建过程中执行,用指定的这些命令对容器内进行修改,最后的镜像是经过这些命令处理过的
    • 可以执行多个RUN,一步步的处理镜像内容。
    CMD和ENTRYPOINT:
    两个都是用这个镜像来创建并执行容器后运行,即docker run之后运行命令
    并且有多个CMD和ENTRYPOINT时,只执行最后一个
    区别如下:
    • CMD:如果执行docker run 某镜像 命令 后面跟了个命令或参数,这个命令或参数会覆盖掉CMD的命令。 比如dockerfile里的命令是CMD ["ls","-a"]
      • 如果用这个镜像执行容器时是docker run 镜像 echo "over",则最后只会运行echo "over" 命令;
      • 如果用这个镜像执行容器时是docker run 镜像 -l ,则最后只会执行l这个参数,便会报错
    • ENTRYPOINT和CMD作用几乎一样,但是不会被docker run 某镜像 命令 的命令或参数覆盖掉,而是在后面追加命令或参数
      • 如果这个镜像执行的容器时是docker run 镜像 echo "over",则最后会运行ls -a echo "over" 命令;
      • 如果用这个镜像执行容器时是docker run 镜像 -l ,则最后会执行ls -al,将参数追加。

    发布镜像

    发布到docker hub

    1. 注册 https://hub.docker.com/ 的账号,并保证可以登录
    1. 在客户端登录
      1. 发布镜像

        发布到阿里云等云服务提供商

        参见官方
      2. docker
      3. 容器
      4. JS中的正则表达式Logseq入门
        Loading...