docker

原理

  • Docker 使用 Google 公司推出的 GO语言进行开发实现,基于 Linux 内核的 cgroupnamespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 版本开始,则进一步演进为使用 runCcontainerd

  • Docker 是基于 OS 层的虚拟化技术之上的容器引擎,实现对进程的封装隔离。开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上。

  • 传统的虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需要的应用进程。容器内的应用进程直接运行在宿主的内核,容器没有自己的内核,也没有硬件虚拟,容器是轻量级的虚拟化技术。

  • img

  • 左图虚拟机的Guest OS层和Hypervisor层在docker中被Docker Engine层所替代。虚拟机的Guest OS即为虚拟机安装的操作系统,它是一个完整操作系统内核;虚拟机的Hypervisor层可以简单理解为一个硬件虚拟化平台,它在Host OS是以内核态的驱动存在的。 虚拟机实现资源隔离的方法是利用独立的OS,并利用Hypervisor虚拟化CPU、内存、IO设备等实现的。 对比虚拟机实现资源和环境隔离的方案,docker就显得简练很多。docker Engine可以简单看成对Linux的NameSpace、Cgroup、镜像管理文件系统操作的封装。docker并没有和虚拟机一样利用一个完全独立的Guest OS实现环境隔离,它利用的是目前Linux内核本身支持的容器方式实现资源和环境隔离。简单的说,docker利用namespace实现系统环境的隔离;利用Cgroup实现资源限制;利用镜像实现根目录环境的隔离。

基本概念

  • Docker Client
    • Docker提供给用户的客户端。Docker Client提供给用户一个终端,用户输入Docker提供的命令来管理本地或者远程的服务器。
  • Docker Daemon
    • Docker服务的守护进程。每台服务器(物理机或虚机)上只要安装了Docker的环境,基本上就跑了一个后台程序Docker Daemon,Docker Daemon会接收Docker Client发过来的指令,并对服务器的进行具体操作。
  • Docker Images
    • 俗称Docker的镜像,这个可难懂了。你暂时可以认为这个就像我们要给电脑装系统用的系统CD盘,里面有操作系统的程序,并且还有一些CD盘在系统的基础上安装了必要的软件,做成的一张 “只读” 的CD。
  • Docker Registry
    • 这个可认为是Docker Images的仓库,就像git的仓库一样,用来管理Docker镜像的,提供了Docker镜像的上传、下载和浏览等功能,并且提供安全的账号管理可以管理只有自己可见的私人image。
  • Docker Container
    • 俗称Docker的容器,这个是最关键的东西了。Docker Container是真正跑项目程序、消耗机器资源、提供服务的地方,Docker Container通过Docker Images启动,在Docker Images的基础上运行你需要的代码。 你可以认为Docker Container提供了系统硬件环境,然后使用了Docker Images这些制作好的系统盘,再加上你的项目代码,跑起来就可以提供服务了。

Docker Imager

  • Docker 镜像是一个root下的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

  • Docker镜像采用分层存储结构(AUFS)。每一层构建好后就不会在变,一层层构建,前一层是后一层的基础,由多层文件系统联合组成。

  • Docker 镜像可以传到 Docker Registry,Docker Registry里面可以创建私有或公共仓库,每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。通过这个分层存储与标签管理,Docker 镜像可以像代码一样,非常方便的拉取,在任何 Docker Egnine上运行,带来全新的运维模式。

  • img

Docker container

  • 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。容器销毁,数据随之被删除。任何保存于容器存储层的信息都会随容器删除而丢失。
  • 镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础。在运行的容器中做文件修改,然后docker commit,就相当于在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。
  • 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

Docker Registry

  • 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
  • 一个 Docker Registry 中可以包含多个 仓库Repository);每个仓库可以包含多个 标签Tag);每个标签对应一个镜像。
  • 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
  • Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest
    仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务

Docker架构

  • Docker采用了C/S架构,包括客户端和服务端。 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者 RESTful API 来进行通信。Docker daemon一般在宿主机后台运行,等待接收来自客户端的消息。

使用镜像

下载

  • Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:
  • $ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
  • Docker 镜像仓库地址:
    • 地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub(docker.io)。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

运行

  • docker run -it –rm ubuntu:18.04 bash
    • –name 指定名称
    • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
    • --rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
    • ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
    • bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash

镜像体积

  • docker image ls 镜像列表
  • docker system df 命令来便捷的查看镜像、容器、数据卷所占用的空间。
  • 这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。比如,ubuntu:18.04 镜像大小,在这里是 63.3MB,但是在 Docker Hub 显示的却是 25.47 MB。这是因为 Docker Hub 中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此 Docker Hub 所显示的大小是网络传输中更关心的流量大小。而 docker image ls 显示的是镜像下载到本地后,展开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。
  • docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多

UnionFS(联合文件系统)

  • 是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像)可以制作各种具体的应用镜像

中间层镜像

  • 为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的 docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数
  • 这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。
  • docker镜像的最底层是引导文件系统bootfs,这一层包含boot加载器和内核,当boot加载完后之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

删除本地镜像

  • docker image rm [选项] <镜像1> [<镜像2> …]
  • 用ID,镜像名字、摘要删除镜像
    • 其中,<镜像> 可以是 镜像短 ID镜像长 ID镜像名 或者 镜像摘要
  • untagged & Deleted
    • 镜像的唯一标识是其 ID 和摘要,而一个镜像可以有多个标签。当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的 Untagged 的信息。因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么 Delete 行为就不会发生。所以并非所有的 docker image rm 都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。
    • 当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为。镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。镜像的多层结构让镜像复用变得非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。这就是为什么,有时候会奇怪,为什么明明没有别的标签指向这个镜像,但是它还是存在的原因,也是为什么有时候会发现所删除的层数和自己 docker pull 看到的层数不一样的原因。
  • 除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在(即使容器没有运行),那么同样不可以删除这个镜像。之前讲过,容器是以镜像为基础,再加一层容器存储层,组成这样的多层存储结构去运行的。因此该镜像如果被这个容器所依赖的,那么删除必然会导致故障。如果这些容器是不需要的,应该先将它们删除,然后再来删除镜像。

容器

  • 启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited)的容器重新启动。因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。
  • 当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
    • 检查本地是否存在指定的镜像,不存在就从 registry 下载
    • 利用镜像创建并启动一个容器
    • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
    • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
    • 从地址池配置一个 ip 地址给容器
    • 执行用户指定的应用程序
    • 执行完毕后容器被终止

守护态运行

  • docker run 的时刻使用**-d**参数,此时容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面(输出结果可以用 docker logs 查看)。
  • docker container logs [container ID or NAMES] 获取守护态的打印信息

终止

  • docker container stop [id/name] 来终止一个运行中的容器
  • 当 Docker 容器中指定的应用终结时,容器也自动终止。
  • 终止状态的容器可以用 docker container ls -a 命令看到

进入容器

  • 使用 -d参数时,容器启动后会进入后台。某些时候需要进入容器进入操作。使用 docker attach 命令或 docker exec 命令,推荐大家使用 docker exec 命令
  • docker attach
    • 进入容器后,如果从这个stdin中exit,会导致容器停止
  • docker exec -it
    • 只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。
      -i -t 参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符
    • 如果从这个 stdin 中 exit,不会导致容器的停止。

容器导入和导出

  • 导出:docker export [id] > xx.tar
    • 导出容器快照到本地文件
  • docker import
    • 从容器快照文件中再导入为镜像,例如 cat ubuntu.tar | docker import - test/ubuntu:v1.0
    • 可以指定URL或者目录来导入
  • 用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

删除容器

  • 删除容器
    • docker container rm 如果要删除一个处于运行中的容器使用-f参数
  • 清除所有处于终止状态的容器
    • docker container ls -a 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用下面的命令可以清理掉所有处于终止状态的容器。
    • docker container prune

仓库

  • 仓库(Repository)是集中存放镜像的地方。
  • 一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 docker.io/ubuntu 来说,docker.io 是注册服务器地址,ubuntu 是仓库名。
  • 注册 docker hub

拉取镜像

  • docker search 命令来查找官方仓库中的镜像
    • 在查找的时候通过 --filter=stars=N 参数可以指定仅显示收藏数量为 N 以上的镜像。
  • docker pull 拉取到本地
    1
    2
    3
    4
    5
    6
    7
    $ docker search centos
    NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    centos The official build of CentOS. 6449 [OK]
    ansible/centos7-ansible Ansible on Centos7 132 [OK]
    consol/centos-xfce-vnc Centos container with "headless" VNC session… 126 [OK]
    jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 117 [OK]
    centos/systemd systemd enabled base container.
  • 括镜像名字、描述、收藏数(表示该镜像的受关注程度)、是否官方创建(OFFICIAL)、是否自动构建 (AUTOMATED)。
  • 根据是否是官方提供,可将镜像分为两类
    • 一种是类似 centos 这样的镜像,被称为基础镜像或根镜像。这些基础镜像由 Docker 公司创建、验证、支持、提供。这样的镜像往往使用单个单词作为名字。
    • 还有一种类型,比如 ansible/centos7-ansible 镜像,它是由 Docker Hub 的注册用户创建并维护的,往往带有用户名称前缀。可以通过前缀 username/ 来指定使用某个用户提供的镜像,比如 ansible 用户。

推送镜像

  • 用户也可以在登录后通过 docker push 命令来将自己的镜像推送到 Docker Hub。
  • docker tag ubuntu:18.04 username/ubuntu:18.04 username 请替换为你的 Docker 账号用户名。

自行构建

  • 2021 年 6 月 18 日之后,该项功能仅限付费用户使用。
  • 自动构建(Automated Builds)功能对于需要经常升级镜像内程序来说,十分方便。自动构建允许用户通过 Docker Hub 指定跟踪一个目标网站(支持 GitHubBitBucket)上的项目,一旦项目发生新的提交 (commit)或者创建了新的标签(tag),Docker Hub 会自动构建镜像并推送到 Docker Hub 中。
  • 配置自动构建
    • 登录 Docker Hub;
    • 在 Docker Hub 点击右上角头像,在账号设置(Account Settings)中关联(Linked Accounts)目标网站;
    • 在 Docker Hub 中新建或选择已有的仓库,在 Builds 选项卡中选择 Configure Automated Builds
    • 选取一个目标网站中的项目(需要含 Dockerfile)和分支;
    • 指定 Dockerfile 的位置,并保存。
  • 配置完成之后可以在 Docker Hub 的仓库页面的 Timeline 选项卡中查看每次构建的状态。

私有仓库

docker-registry

docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库

Nexus

数据管理

  • ,在容器中管理数据主要有两种方式:

数据卷

  • 数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
    • 数据卷 可以在容器之间共享和重用
    • 数据卷 的修改会立马生效
    • 数据卷 的更新,不会影响镜像
    • 数据卷 默认会一直存在,即使容器被删除
  • 注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。
  • 在wsl2模式的win下,所有的数据在以下目录中,通过浏览器访问
    • \wsl$\docker-desktop-data
    • \wsl$\docker-desktop
    • file://wsl%24/docker-desktop-data/version-pack-data/community/docker/volumes/

数据卷的操作

  • 创建
    • docker volume create my-vol
  • 查看所有的数据卷
    • docker volume ls
  • 在主机中查看指定数据卷的信息
    • docker volume inspect my-vol
  • 启动一个挂载数据卷的容器
    • 在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷
    • 下面创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /usr/share/nginx/html 目录。
      • docker run -d -P
        ​ –name web \

      ​ # -v my-vol:/usr/share/nginx/html
      ​ –mount source=my-vol,target=/usr/share/nginx/html
      ​ nginx:alpine

  • 查看数据卷的具体信息
    • 在主机中使用 docker inspect [name] 来查看指定容器的信息
    • 数据卷 信息在 “Mounts” Key 下面
  • 删除数据卷
    • 数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。
    • 无主的数据卷可能会占据很多空间,要清理请使用以下命令
      • docker volume prune

挂载主机目录

  • 使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去。也可以挂载单个文件
    1
    2
    3
    4
    5
    $ docker run -d -P \
    --name web \
    # -v /src/webapp:/usr/share/nginx/html \
    --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html ,readonly(只读操作)\
    nginx:alpine
    • 上面的命令加载主机的 /src/webapp 目录到容器的 /usr/share/nginx/html目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错
    • Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读
  • 查看挂在目录的具体信息
    • docker inspect web

网络

  • 使用docker port来查看当前映射的端口配置
  • docker inspect 来产看dokcer可变的网络配置

网络模式

  • 网络模式 简介 命令
    bridge 为每一个容器分配、配置IP等,并将容器连接到一个 docker0 虚拟网桥,默认为该模式 –network bridge
    host 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口 –network host
    none 容器有独立的NetWork namespace ,但没有对其进行任何网络设置,如分配veth pair和网络桥接,IP等 –network none
    container 新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等 –network container:Name/容器ID

docker0

  • docker 服务默认会创建一个docker0网桥(其中有一个docker0内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到了一个物理网络。Docker默认制定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥通信。

  • docker0

    • 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通
    • 每个容器实例内部也有一块网卡,每个接口都叫eth0
    • docker0上面的每个veth匹配某个容器实例内部的eth0,两两配队,一一匹配、
    • 通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的IP,此时容器间的网络是互通的

host

  • docker-host

    • 容器将不会获得一个独立的Network Namespace 而是和宿主机共用一个Network Namespace .容器将不会模拟出自己的网卡而是使用宿主机的IP和端口

none

  • 禁用网络,不连接外网

container

  • docker-network-container

    • 新建的容器和已经存在的容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他如文件系统、进程列表等还是隔离的。

自定义网络模式

  • 自定义网络本身就维护好了主机名和ip的对应关系
  • 新建自定义网络
    • docker network create xy_network
  • 新建容器加入上一步新建的自定义网络
    • docker run -d -p 8081:8080 –network xy_network –name tomcat81 billygoo/tomcat8-jdk8
    • docker run -d -p 8082:8080 –network xy_network –name tomcat82 billygoo/tomcat8-jdk8

外部访问容器

  • 容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射。
  • -p:指定映射的端口 -P:随机映射的端口
  • docker run -d -p 80:80 nginx:alpine
    • 映射本地的指定的端口到容器的指定端口

容器互联

  • 随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数。
  • 新建网络
    • docker network create -d bridge my-net
      • -d 指定网络类型
        • bridge
        • overlay :用于Swarm mode(集群模式)
  • docker run -it –rm –name busybox1 –network my-net busybox sh // docker run -it –rm –name busybox2 –network my-net busybox sh
  • 两个连接到一个网络则容器互联成功

Docker File

  • 注意事项
    • 每个保留字指令都必须为大写字母且后面要跟随至少一个参数
    • 每条指令都会创建一个新的镜像层并对镜像进行提交

关键字

  • FROM
    • 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,dockerfile的第一条指令必须是FROM
  • RUN
    • 容器构建时需要运行的命令
  • EXPOSE
    • 当前容器对外暴露出的端口
  • WORKDIR
    • 指定在创建容器后,默认终端登录的默认目录
  • USER
    • 指定该镜像以什么样的用户去执行,默认为root
  • ENV
    • 用来在构建镜像过程中设置环境变量
  • VOLUME
    • 容器卷
  • ADD
    • 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
    • 注意:如果源路径是个文件,且目标路径是不是以 / 结尾,则docker会把目标路径当作一个文件。
  • COPY
    • 类似ADD,拷贝文件到镜像中
    • 将从构建上下文目录中<源路径>的文件复制到新的一层的镜像内的<目标路径>位置
  • CMD
    • 启动容器启动后初始化应用的命令
    • DockerFIle中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
    • shell 格式:CMD <命令>
      exec 格式:CMD [“可执行文件”, “参数1”, “参数2”…]
      参数列表格式:CMD [“参数1”, “参数2”…]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
  • ENTRYPONT
    • 也是用来指定一个容器启动时要运行的命令
    • 类似于CMD指令,但是ENTRYPONT不会被docker run 后面的命令覆盖,而且这些命令行参数会被当作参数送给ENTRYPONT指令指定的程序

docker示例文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM amazoncorretto:8-al2-jdk
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
# see https://www.apache.org/dist/tomcat/tomcat-9/KEYS
# see also "versions.sh" (https://github.com/docker-library/tomcat/blob/master/versions.sh)
ENV GPG_KEYS 48F8E69F6390C9F25CFEDCD268248959359E722B A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243
ENV TOMCAT_MAJOR 9
ENV TOMCAT_VERSION 9.0.73
ENV TOMCAT_SHA512 d43fbd6c5ae00bc0ffc2559743f91abd3547c827426cb0acdc8428e060e8659b6bb41b3877deb061ab6202980de39b9558525a4256725b647d5bff93e47a5664
# smoke test
catalina.sh version
# verify Tomcat Native is working properly
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"]

docker compose

核心概念

  • 一个文件
    • docker-compose.yml
  • 两个要素
    • 服务
      • 一个个应用容器实例,比如订单微服务、库存微服务、mysql容器或者redis
    • 工程
      • 由一组关联的应用容器组成的一个完整的业务单元,在docker-compose.yml文件中定义

常用命令

  • docker compose up
    • -d 后台运行
    • 启动所有的docker compose 服务
  • docker compose down
    • 停止并删除容器、网络、卷、镜像
  • docker compose exec yml中的服务id
    • 进入容器实例内部
  • docker compose ps
    • 展示当前docker-compose编排过的运行的所有容器
  • docker compose top
    • 展示当前docker-compose编排过的容器进程
  • docker-compose config -q
    • 检查配置,有问题才有输出
  • docker-compose restart # 重启服务
  • docker-compose start # 启动服务
  • docker-compose stop # 停止服务

compos0e

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 版本
version: "3"
# 要启动的容器
services:
microService:
image: zzyy_docker:1.6
container_name: ms01
ports:
- "6001:6001"
volumes:
- /app/microService:/data
networks:
- atguigu_net
depends_on:
- redis
- mysql

redis:
image: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /app/redis/redis.conf:/etc/redis/redis.conf
- /app/redis/data:/data
networks:
- atguigu_net
command: redis-server /etc/redis/redis.conf

mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2021'
MYSQL_USER: 'zzyy'
MYSQL_PASSWORD: 'zzyy123'
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- atguigu_net
command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
# 定义网络模式
networks:
atguigu_net:


docker
https://x-leonidas.github.io/2022/02/01/15云和容器/docker/
作者
听风
发布于
2022年2月1日
更新于
2025年5月1日
许可协议