首页 Docker 基础
文章
取消

Docker 基础

介绍

Docker 是一组平台即服务 (PaaS) 产品,它们使用操作系统级虚拟化以容器的镜像形式交付软件。容器之间彼此隔离,可以通过特定的方式进行通讯。

镜像

Docker容器镜像是一个轻量、独立、可执行的软件包,其中包含运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。

容器

容器是打包代码及其所有依赖项的标准软件单元,因此应用程序可以从一个计算环境快速可靠地运行到另一个计算环境。 镜像在Docker引擎中运行时成为容器。容器会将软件与其环境隔离,确保它能够一致地工作,即使在不同的操作系统中。例如:Windows、Linux或MacOS

网络

通过网络配置,Docker可以将多个容器链接在一起或者将它们连接到非Docker的工作负载中。

网络驱动

  • bridge: 默认网络驱动。bridge网络通常用于当独立运行的容器之间需要交流时。
  • host: 对于独立容器,去掉容器和Docker主机之间的网络隔离,直接使用主机的网络。
  • overlay: overlay网络将多个Docker守护进程连接在一起,并使 swarm 服务能够相互通信。您还可以使用overlay网络来促进 swarm 服务和独立容器之间的通信,或者不同 Docker 守护进程上的两个独立容器之间的通信。这种策略消除了在这些容器之间进行操作系统级路由的需要
  • macvlan: Macvlan 网络允许您为容器分配 MAC 地址,使其在您的网络上显示为物理设备。 Docker 守护进程通过容器的 MAC 地址将流量路由到容器。 在处理期望直接连接到物理网络而不是通过 Docker 主机的网络堆栈路由的遗留应用程序时,使用macvlan驱动程序有时是最佳选择。
  • none: 对于此容器,禁用所有网络。 通常与自定义网络驱动程序结合使用

网络小结

  • 当您需要多个容器在同一个 Docker 主机上进行通信时,User-defined bridge networks是最佳选择。
  • 当网络堆栈不应与 Docker 主机隔离,但您希望容器的其他方面被隔离时,host networks是最佳选择。
  • 当您需要在不同 Docker 主机上运行的容器进行通信时,或者当多个应用程序使用 swarm 服务协同工作时,overlay networks是最佳选择。
  • 当您从 VM 设置迁移或需要容器看起来像网络上的物理主机时,Macvlan networks是最佳选择,每个主机都有唯一的 MAC 地址。
  • 第三方网络插件允许您将 Docker 与专门的网络堆栈集成。

数据管理

默认情况下,在容器内创建的所有文件都存储在可写容器层上。 这意味着:

  • 当该容器不再存在时,数据不会持久存在,并且如果另一个进程需要数据,则很难将数据从容器中取出。
  • 容器的可写层与运行容器的主机紧密耦合。 您无法轻松地将数据移动到其他地方。
  • 写入容器的可写层需要存储驱动程序来管理文件系统。 存储驱动程序使用 Linux 内核提供联合文件系统。 与使用直接写入主机文件系统的数据卷相比,这种额外的抽象会降低性能。

Volume

卷是持久化 Docker 容器生成和使用的数据的首选机制。

Docker Hub

Docker Hub 是一个公共的注册中心,任何人都可以使用,默认配置下,Docker将会在这里寻找镜像

Dockerfile

Docker 可以依照 Dockerfile 的内容,自动化地构建镜像。 Dockerfile 是包含着用户所需的如何构建镜像的所有命令的文本

1
docker build -t app:tag .

镜像构建上下文(context)

docker build命令最后有一个., .表示当前目录。由于很多情况Dockerfile就在当前目录,所以很容易理解成指定Dockerfile 的目录。其实.是指定上下文的路径。举个栗子:

1
COPY ./package.json /app/

这个指令表示复制当前上下文目录下的package.json,而不是Dockerfile所在目录下的package.json.

关键词

  • FROM 指定基础镜像 定制镜像,就是在以一个镜像为基础,在其上进行定制。 除了选择现有的基础镜像外,Docker还存在一个特殊的镜像,名为scratch,这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
  • RUN执行命令 RUN指令是用来执行命令行命令的。由于命令行的强大能力,RUN指令在定制镜像时是最常用的指令之一。其格式有两种:
    1. shell格式: RUN <命令>
    1
    
       RUN ls
    
    1. exec格式: RUN ["可执行文件", "参数1", "参数2"]

我们能否每一个命令对应一个RUN呢? Dockerfile中每一个指令都会建立一层,RUN也不例外,每一个RUN的行为,都会新建立一层,在其上执行这些命令,执行结束后,commit这一层的修改,构成新的镜像。 这样是没有意义的。结果会导致我们的镜像非常臃肿、非常多的层,增加构建部署时间,也容易出错

  • COPY 复制文件 用法:
    • COPY <源路径>... <目标路径>
    • COPY ["<源路径1>", ... "<目标路径>"]

<源路径>可以是多个,甚至可以是通配符,其通配符规则要满足Go的filepath.Match规则。如:

1
2
COPY hom* /mydir/
COPY hom?.txt /mydir/

使用COPY指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。

  • ADD 高级的复制文件 ADD指令和COPY 的格式和性质基本一致。但是在COPY的基础上增加了一些功能。
    • 源路径是一个URL Docker引擎会视图去下载这个链接的文件放到<target path>去。下载后的文件权限自动设置为600, 如果不是想要的,需额外增加一层RUN去修改文件权限。如果下载的是一个压缩包,也需要一层RUN去解压缩。因此这个功能并不实用,不推荐使用
    • 源路径是一个tar压缩文件 压缩格式为gzip,bzip2以及xz的情况下,ADD指令会自动解压缩这个文件到<target path>中。在某些情况下,自动解压缩非常有用,但是某些情况下我们希望复制个压缩文件进去,而不是解压缩,这时就不可以使用ADD命令了。 在Docker官方的最佳实践中要求,尽可能的使用COPY,因为COPY的语义很明确,就是复制文件,而ADD则包含了更复杂的功能,其行为也不一定很清晰。 ADD指令会令镜像构建缓存失效,从而可能会令镜像构建变得缓慢。
  • CMD容器启动命令 用法:
    1
    2
    
      CMD <command>
      CMD ["<executable file>", "<arg1>", "<arg2>"...]
    

Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样。容器内没有后台服务的概念。

  • ENTERPOINT 入口点

ENTERPOINTRUN一样,分为exec格式和shell格式。

当指定了ENTERPOINT后,CMD的含义就发生了变化,不在是直接执行器命令,而是将CMD的内容作为参数传给ENTERPOINT指令,换句话说实际执行时,变为:

1
<ENTERPOINT> "<CMD>"
  • ENV环境变量 格式:
    • ENV <key> <value>
    • ENV <key1>=<value1> <key2>=<value2> ...
  • ARG 构建参数 格式:
1
ARG <参数名>[=<默认值>]

构建参数和ENV的效果一样,都是设置环境变量,所不同的是ARG设置的是构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

Dockerfile中的ARG指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令docker build 中用--build-arg <参数名>=<值>来覆盖。

本文由作者按照 CC BY 4.0 进行授权