Docker 学习与实践




文章目录

  • Docker 学习与实践
  • Docker基本概念
  • Docker 镜像
  • Docker 容器
  • Docker Registry
  • Docker Registry 公开服务
  • Docker Registry 私有服务
  • Docker 镜像使用
  • 获取镜像
  • 列出镜像
  • 删除本地镜像
  • Dockerfile 定制镜像
  • FROM
  • RUN
  • CMD
  • LABEL
  • EXPOSE
  • ENV
  • ADD
  • COPY
  • ENTRYPOINT
  • USER
  • WORKDIR
  • ARG
  • 总结



Docker 学习与实践

Docker基本概念

Docker是一个新的容器化的技术,它轻巧,且易移植;
Docker 包括三个基本概念:
镜像(Image )
容器(Container )
仓库(Repository )
理解了这三个概念,就理解了 Docker 的整个生命周期。

Docker 镜像

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)

Docker 容器

镜像(Image ) 和容器(Container ) 的关系,就像是面向对象程序设计中的 类 和 实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等

Docker Registry

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository ) ;每个仓库可以包含多个标签(Tag ) ;每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。
我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

Docker Registry 公开服务

Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务,最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry

Docker Registry 私有服务

docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库
http://dockerhub.***.com

Docker 镜像使用

获取镜像

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

比如:

$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:16.04

上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub 获取镜像。而镜像名称是 ubuntu:16.04 ,因此将会获取官方镜像 library/ubuntu 仓库中标签16.04 的镜像。

列出镜像

要想列出已经下载下来的镜像,可以使用 docker image ls 命令。

$ docker image ls

Docker 课程申报书_Dockerfile


列表包含了 仓库名 、 标签 、 镜像 ID 、创建时间 以及 所占用的空间镜像

ID则是镜像的唯一标识,一个镜像可以对应多个标签

删除本地镜像

如果要删除本地的镜像,可以使用 docker image rm 命令
其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> …]

Dockerfile 定制镜像

每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。Dockerfile 是一个文本文件,其内包含了一条条的指令

FROM

1)功能为指定基础镜像,并且必须是第一条指令。
2)如果不以任何镜像为基础(表示一个空白的镜像),那么写法为:FROM scratch:
如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作
为镜像第一层开始存在语法:

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest> 
三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest

RUN

功能为运行指定的命令

RUN命令有两种格式
1. RUN <command>
2. RUN ["executable", "param1", "param2"]

1)第一种后边直接跟shell命令
在linux操作系统上默认 /bin/sh -c
在windows操作系统上默认 cmd /S /C
2)第二种是类似于函数调用。
可将executable理解成为可执行文件,后面就是两个参数。
3)两种写法比对:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
RUN ["/bin/bash", “-c”, “echo hello”]
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。RUN书写时的换行符是
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过127 层。

CMD

功能为容器启动时要运行的命令
语法有三种写法

  1. CMD [“executable”,“param1”,“param2”]
  2. CMD [“param1”,“param2”]
  3. CMD command param1 param2
    第三种比较好理解了,就时shell这种执行方式和写法
    第一种和第二种其实都是可执行文件加上参数的形式
    举例说明两种写法:
CMD [ "sh", "-c", "echo $HOME" ]
CMD [ "echo", "$HOME" ]

注:这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。
原因是参数传递后,docker解析的是一个JSON array
RUN & CMD
不要把RUN和CMD搞混了。RUN是构件容器时就运行的命令以及提交运行结果
CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子

LABEL

功能是为镜像指定标签

语法:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
 一个Dockerfile种可以有多个LABEL,

EXPOSE

功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数

ENV

功能为设置环境变量

语法有两种
1. ENV <key> <value>
2. ENV <key>=<value> ...

两者的区别就是第一种是一次设置一个,第二种是一次设置多个

ADD

一个复制命令,把文件复制到镜像中。
如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用。

语法如下:
1. ADD <src>... <dest>
2. ADD ["<src>",... "<dest>"]

路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
可以是一个本地文件或者是一个本地压缩文件,还可以是一个url
如果把写成一个url,那么ADD就类似于wget命令
如以下写法都是可以的:
ADD test relativeDir/
ADD test /relativeDir
ADD http://example.com/foobar /

尽量不要把写成一个文件夹,如果是一个文件夹了,复制整个目录的内容,包括文件系统元数据

COPY

看这个名字就知道,又是一个复制命令

语法如下:
1. COPY <src>... <dest>
2. COPY ["<src>",... "<dest>"]

COPY与ADD的区别: COPY的只能是本地文件,其他用法一致

ENTRYPOINT

功能是启动时的默认命令
语法如下:

  1. ENTRYPOINT [“executable”, “param1”, “param2”]
  2. ENTRYPOINT command param1 param2
    第一种就是可执行文件加参数
    第二种就是写shell
    与CMD比较说明(这俩命令太像了,而且还可以配合使用):
    相同点:
    1)只能写一条,如果写了多条,那么只有最后一条生效
    2)容器启动时才运行,运行时机相同
    不同点:
    1)ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖
    2)如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数
    VOLUME
    可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种
    语法为:
    VOLUME ["/data"]
    说明:["/data"]可以是一个JsonArray ,也可以是多个值。
    所以如下几种写法都是正确的
    VOLUME ["/var/log/"]
    VOLUME /var/log
    VOLUME /var/log /var/db

一般的使用场景为需要持久化存储数据时,容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。所以当数据需要持久化时用这个命令。

USER

设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的
USER daemo
USER UID

注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行

WORKDIR

语法:
WORKDIR /path/to/workdir
设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
pwd执行的结果是/a/b/c

WORKDIR也可以解析环境变量;如:
ENV DIRPATH /path
WORKDIR Docker 课程申报书_docker_02DIRNAME
RUN pwd
pwd的执行结果是/path/$DIRNAME

ARG

语法:
ARG <name>[=<default value>]

设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg =来指定参数
如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning

总结

下一节讲述docker容器的实例实践