Docker之 – 使用镜像和仓库(二)

查找镜像

我们可以通过 docker search 命令来查找所有 Docker Hub 上公共可用的镜像,如下

Docker之 - 使用镜像和仓库(二)

下面还有很多镜像,我们主要看一下每条镜像都返回了哪些内容

  • 仓库名称
  • 镜像描述
  • 用户评价 --- 反应一个镜像的受欢迎程度
  • 是否官方 --- 是否由Docker 公司及其指定厂商开发的镜像
  • 是否自动构建 --- 表示这个镜像是由 Docker Hub 自动构建的

从上面查询的结果中选择一个镜像进行拉取,docker pull jamtur01/puppetmaster这条命令将会下载 jamtur01/puppetmaster镜像到本地。

接下来就可以使用这个镜像来构建一个容器,下面就用 docker run 命令构建一个容器

Docker之 - 使用镜像和仓库(二)

查看版本号

Docker之 - 使用镜像和仓库(二)

构建镜像

上面我们看到如何拉取并且构建好带有定制内容的 Docker 镜像,那么我们如何修改自己的镜像,并且管理和更新这些镜像呢?

  • 使用 docker commit 命令
  • 使用 docker build 命令和 Dockerfile 文件

现在我们不推荐使用 docker commit 命令,相反应该使用更灵活更强大的 Dockerfile 来构建镜像。不过,为了对 Docker 又一个更深的了解,我们还是会先介绍一下 docker commit 构建镜像。之后,我们重点介绍Docker 所推荐的构建方法:编写 Dockerfile 之后使用 docker build 命令。

创建Docker Hub 账号

构建镜像中很重要的一环就是如何共享和发布镜像。可以将镜像推送到 Docker Hub中或者自己的私有 Registry 中。为了完成这项工作,需要在 Docker Hub上创建一个账号

如果你还没有Docker 通行证,在 hub.docker.com 注册一个,记下你的用户名,登录本地计算机上的Docker公共注册表。使用docker login,输入用户名和密码进行登录

Docker之 - 使用镜像和仓库(二)

你的个人信息会保存在 $HOME/.dockercfg 文件中

使用 Docker 的commit 命令创建镜像

创建 Docker镜像的第一种方式是使用 docker commit 命令。可以将此想象为我们是在版本控制系统里面提交变更,毕竟这和 git commit 命令真是太像了。

我们先从创建一个容器开始,这个容器基于我们前面见过的 ubuntu 镜像。如下

Docker之 - 使用镜像和仓库(二)

接下来,我们在 ubuntu 中安装 apache 服务器,使用apt-get -yqq updateapt-get -y install apache2 命令。

Docker之 - 使用镜像和仓库(二)

我们启动了一个容器,并安装了 Apache 服务器,我们会将这个服务器作为 Web 服务器运行,所以我们想把它当前状态保存起来。这样下次启动就不用重新安装了。为了完成这项工作,需要先使用 exit 从 ubuntu 中退出,之后再运行 docker commit 命令。如下

Docker之 - 使用镜像和仓库(二)

我们看到,在上图所示的 docker commit 命令中,指定了要提交修改过的容器ID(可以通过 docker ps -l -q 命令得到刚刚创建的容器 ID),以及一个镜像仓库和镜像名,这里是 jamtur01/puppetmaster

可以使用 docker images jamtur01/puppetmaster 命令查看刚刚创建的镜像。

Docker之 - 使用镜像和仓库(二)

这条命令中我们使用 -m(message) 指定提交信息,同时指定了 --authro 选项,列出镜像作者信息。接着列出了想要提交的容器ID, 最后指定了 jamtur01/puppetmaster ,并为其打上了 webserver 的tag 标签。

可以使用 docker inspect 命令来查看新创建的镜像的详细信息。

Docker之 - 使用镜像和仓库(二)

使用 Dockerfile 构建镜像

我们并不推荐使用 docker commit 方法来构建镜像。相反,我们推荐使用 Dockerfiledocker build的命令来构建镜像。Dockerfile 使用基于 DSL 语法的指令来构建一个 Docker 镜像,之后使用 docker build 命令基于 Dockerfile 中的指令构建一个新的镜像。

我们的第一个 Dockerfile

下面我们创建一个目录并初始化 Dockerfile,我们创建一个包含简单web服务器的Docker镜像

Docker之 - 使用镜像和仓库(二)

如上图所示,我们在 /usr/local/docker 目录下创建了一个 static_web 的目录,再创建了一个 Dockerfile 文件。那么这个 static_web 目录就是我们的构建环境。Docker 称此环境为上下文(context)或者 构建上下文(build context)Docker 会在构建镜像时将构建上下文和该上下文中的文件和目录上传到 Docker 守护进程。这样 Docker 守护进程就可以直接访问你镜像中的 代码、文件和数据。

下面是一个通过 Dockerfile 来构建 web 服务器的 Docker 镜像

# Version: 0.0.1
FROM ubuntu:14.04
MAINTAINER James Turnbull "james@example.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi, I am in your container' \
        >/usr/share/nginx/html/index.html
EXPOSE 80

该 Dockerfile 由一系列指令和参数组成。每条指令,如FROM,都必须为大写字母,而且后面要跟随一个参数: FROM ubuntu:14.04。Dockerfile 中的指令会按照顺序由上向下执行,所以编写 Dockerfile 时,请注意它的顺序。

如果不能使用 :wq 来进行保存的话,请首先使用 sudo su切换到管理员模式,然后就可以保存啦。

每条指令都会创建一个新的镜像层并对镜像进行提交。Docker 大体按照如下流程执行 Dockerfile 指令

  • Docker 从基础镜像运行一个容器
  • 执行一条指令,对容器作出修改
  • 执行类似docker commit 操作,提交一个新的镜像层
  • Docker 再基于刚提交的镜像运行一个新容器
  • 执行 Dockerfile 中的下一条指令,直到所有指令都执行完毕

从上面可以看出,如果你的Dockerfile 由于某些原因(例如指令失败了)没有正常结束,那么你将得到了一个可以使用的镜像。这对调试很有帮助:可以基于镜像运行一个具备交互功能的容器,使用最后创建的镜像对你最后失败的指令做出调试

Dockerfile 也支持中文注释,以 # 开头的行都会被认为是注释。Dockerfile 中的第一行就是注释的例子

每个 Dockerfile 的第一行指令都应该是 FROM。FROM指令指定一个已经存在的镜像,后续指令都将基于该镜像进行,这个镜像被称为基础镜像(base image)。

  • 在上面的示例中,我们使用了 ubuntu:14.04 作为新镜像基础镜像。基于这个 Dockerfile 构建的新镜像以 Ubuntu 14.04 操作系统为基础。再运行一个容器时,必须要指明基于哪个基础镜像进行构建。
  • 接着指定了 MAINTAINER 指令,这条指令会告诉 Docker 该镜像的作者是谁,以及作者的电子邮件地址,这有助于标示镜像的所有者以及联系方式。
  • 在这些指令之后,我们指定了三条 RUN 指令。RUN指令会在当前的镜像中运行指定的命令。在这个例子中,我们通过 RUN 指令更新了已经安装的 APT 仓库,安装了 nginx 包,之后创建了 /usr/share/nginx/html/index.html 文件,该文件由一些简单的示例文本。像前面说的那样,每条RUN指令都会创建一个新的镜像层,如果该命令执行成功,就会将此镜像提交,继续执行下一条指令

默认情况下,RUN指令会在shell里使用命令包装器 /bin/sh -c 来执行。如果是在一个不支持 shell 的平台上运行或者不希望在 shell 中运行,也可以使用 exec 格式的 RUN 指令

如下 : RUN["apt-get", "install", "-y", "nginx"]

在这种方式中,我们使用数组的方式来指定要运行的命令和要传递的参数。

  • 接着设置了 EXPOSE 命令,这条执行告诉 Docker 容器内的应用程序将会使用容器的指定接口。这并不意味着可以自动访问任意容器运行中的服务端口,可以指定多个 EXPOSE 指令向外公开多个端口。

基于 Dockerfile 构建新

执行 docker build 命令时,Dockerfile 中的所有指令都会被执行并且提交,并且在命令成功结束后返回一个新镜像,下面就来看看如何构建一个新镜像。

一定不要忘记最后面有个空格 和. ,也可以在构建镜像的过程中为镜像设置一个标签:使用方法为“镜像名 : 标签”,如下所示

            </div>

查找镜像

我们可以通过 docker search 命令来查找所有 Docker Hub 上公共可用的镜像,如下

Docker之 - 使用镜像和仓库(二)

下面还有很多镜像,我们主要看一下每条镜像都返回了哪些内容

  • 仓库名称
  • 镜像描述
  • 用户评价 --- 反应一个镜像的受欢迎程度
  • 是否官方 --- 是否由Docker 公司及其指定厂商开发的镜像
  • 是否自动构建 --- 表示这个镜像是由 Docker Hub 自动构建的

从上面查询的结果中选择一个镜像进行拉取,docker pull jamtur01/puppetmaster这条命令将会下载 jamtur01/puppetmaster镜像到本地。

接下来就可以使用这个镜像来构建一个容器,下面就用 docker run 命令构建一个容器。

Docker之 - 使用镜像和仓库(二)

查看版本号

Docker之 - 使用镜像和仓库(二)

构建镜像

上面我们看到如何拉取并且构建好带有定制内容的 Docker 镜像,那么我们如何修改自己的镜像,并且管理和更新这些镜像呢?

  • 使用 docker commit 命令
  • 使用 docker build 命令和 Dockerfile 文件

现在我们不推荐使用 docker commit 命令,相反应该使用更灵活更强大的 Dockerfile 来构建镜像。不过,为了对 Docker 又一个更深的了解,我们还是会先介绍一下 docker commit 构建镜像。之后,我们重点介绍Docker 所推荐的构建方法:编写 Dockerfile 之后使用 docker build 命令。

创建Docker Hub 账号

构建镜像中很重要的一环就是如何共享和发布镜像。可以将镜像推送到 Docker Hub中或者自己的私有 Registry 中。为了完成这项工作,需要在 Docker Hub上创建一个账号

如果你还没有Docker 通行证,在 hub.docker.com 注册一个,记下你的用户名,登录本地计算机上的Docker公共注册表。使用docker login,输入用户名和密码进行登录

Docker之 - 使用镜像和仓库(二)

你的个人信息会保存在 $HOME/.dockercfg 文件中

使用 Docker 的commit 命令创建镜像

创建 Docker镜像的第一种方式是使用 docker commit 命令。可以将此想象为我们是在版本控制系统里面提交变更,毕竟这和 git commit 命令真是太像了。

我们先从创建一个容器开始,这个容器基于我们前面见过的 ubuntu 镜像。如下

Docker之 - 使用镜像和仓库(二)

接下来,我们在 ubuntu 中安装 apache 服务器,使用apt-get -yqq updateapt-get -y install apache2 命令。

Docker之 - 使用镜像和仓库(二)

我们启动了一个容器,并安装了 Apache 服务器,我们会将这个服务器作为 Web 服务器运行,所以我们想把它当前状态保存起来。这样下次启动就不用重新安装了。为了完成这项工作,需要先使用 exit 从 ubuntu 中退出,之后再运行 docker commit 命令。如下

Docker之 - 使用镜像和仓库(二)

我们看到,在上图所示的 docker commit 命令中,指定了要提交修改过的容器ID(可以通过 docker ps -l -q 命令得到刚刚创建的容器 ID),以及一个镜像仓库和镜像名,这里是 jamtur01/puppetmaster

可以使用 docker images jamtur01/puppetmaster 命令查看刚刚创建的镜像。

Docker之 - 使用镜像和仓库(二)

这条命令中我们使用 -m(message) 指定提交信息,同时指定了 --authro 选项,列出镜像作者信息。接着列出了想要提交的容器ID, 最后指定了 jamtur01/puppetmaster ,并为其打上了 webserver 的tag 标签。

可以使用 docker inspect 命令来查看新创建的镜像的详细信息。

Docker之 - 使用镜像和仓库(二)

使用 Dockerfile 构建镜像

我们并不推荐使用 docker commit 方法来构建镜像。相反,我们推荐使用 Dockerfiledocker build的命令来构建镜像。Dockerfile 使用基于 DSL 语法的指令来构建一个 Docker 镜像,之后使用 docker build 命令基于 Dockerfile 中的指令构建一个新的镜像。

我们的第一个 Dockerfile

下面我们创建一个目录并初始化 Dockerfile,我们创建一个包含简单web服务器的Docker镜像

Docker之 - 使用镜像和仓库(二)

如上图所示,我们在 /usr/local/docker 目录下创建了一个 static_web 的目录,再创建了一个 Dockerfile 文件。那么这个 static_web 目录就是我们的构建环境。Docker 称此环境为上下文(context)或者 构建上下文(build context)Docker 会在构建镜像时将构建上下文和该上下文中的文件和目录上传到 Docker 守护进程。这样 Docker 守护进程就可以直接访问你镜像中的 代码、文件和数据。

下面是一个通过 Dockerfile 来构建 web 服务器的 Docker 镜像

# Version: 0.0.1
FROM ubuntu:14.04
MAINTAINER James Turnbull "james@example.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi, I am in your container' \
        >/usr/share/nginx/html/index.html
EXPOSE 80

该 Dockerfile 由一系列指令和参数组成。每条指令,如FROM,都必须为大写字母,而且后面要跟随一个参数: FROM ubuntu:14.04。Dockerfile 中的指令会按照顺序由上向下执行,所以编写 Dockerfile 时,请注意它的顺序。

如果不能使用 :wq 来进行保存的话,请首先使用 sudo su切换到管理员模式,然后就可以保存啦。

每条指令都会创建一个新的镜像层并对镜像进行提交。Docker 大体按照如下流程执行 Dockerfile 指令

  • Docker 从基础镜像运行一个容器
  • 执行一条指令,对容器作出修改
  • 执行类似docker commit 操作,提交一个新的镜像层
  • Docker 再基于刚提交的镜像运行一个新容器
  • 执行 Dockerfile 中的下一条指令,直到所有指令都执行完毕

从上面可以看出,如果你的Dockerfile 由于某些原因(例如指令失败了)没有正常结束,那么你将得到了一个可以使用的镜像。这对调试很有帮助:可以基于镜像运行一个具备交互功能的容器,使用最后创建的镜像对你最后失败的指令做出调试

Dockerfile 也支持中文注释,以 # 开头的行都会被认为是注释。Dockerfile 中的第一行就是注释的例子

每个 Dockerfile 的第一行指令都应该是 FROM。FROM指令指定一个已经存在的镜像,后续指令都将基于该镜像进行,这个镜像被称为基础镜像(base image)。

  • 在上面的示例中,我们使用了 ubuntu:14.04 作为新镜像基础镜像。基于这个 Dockerfile 构建的新镜像以 Ubuntu 14.04 操作系统为基础。再运行一个容器时,必须要指明基于哪个基础镜像进行构建。
  • 接着指定了 MAINTAINER 指令,这条指令会告诉 Docker 该镜像的作者是谁,以及作者的电子邮件地址,这有助于标示镜像的所有者以及联系方式。
  • 在这些指令之后,我们指定了三条 RUN 指令。RUN指令会在当前的镜像中运行指定的命令。在这个例子中,我们通过 RUN 指令更新了已经安装的 APT 仓库,安装了 nginx 包,之后创建了 /usr/share/nginx/html/index.html 文件,该文件由一些简单的示例文本。像前面说的那样,每条RUN指令都会创建一个新的镜像层,如果该命令执行成功,就会将此镜像提交,继续执行下一条指令

默认情况下,RUN指令会在shell里使用命令包装器 /bin/sh -c 来执行。如果是在一个不支持 shell 的平台上运行或者不希望在 shell 中运行,也可以使用 exec 格式的 RUN 指令

如下 : RUN["apt-get", "install", "-y", "nginx"]

在这种方式中,我们使用数组的方式来指定要运行的命令和要传递的参数。

  • 接着设置了 EXPOSE 命令,这条执行告诉 Docker 容器内的应用程序将会使用容器的指定接口。这并不意味着可以自动访问任意容器运行中的服务端口,可以指定多个 EXPOSE 指令向外公开多个端口。

基于 Dockerfile 构建新

执行 docker build 命令时,Dockerfile 中的所有指令都会被执行并且提交,并且在命令成功结束后返回一个新镜像,下面就来看看如何构建一个新镜像。

一定不要忘记最后面有个空格 和. ,也可以在构建镜像的过程中为镜像设置一个标签:使用方法为“镜像名 : 标签”,如下所示