第4章 使用Docker镜像和仓库–小铁笔记

3年前 (2016-02-16) admin 《第一本Docker书》 0评论 已收录 1206℃

第4章 使用Docker镜像和仓库

4.1 什么是Docker镜像

Docker镜像是有文件系统叠加而成。最底端是一个引导文件系统,即bootfs。

Docker用户几乎永远不会和引导文件系统有什么交互。实际上,当一个容器启动后,

它将会被转移到内存中,而引导文件系统则会被卸载,以留出更多的内存供initrd

磁盘镜像使用。

Docker一个镜像可以放到另一个镜像的顶部。位于下面的镜像称为父镜像(parent image),

可以依次类推,直到镜像栈的的最底部,最底部的镜像称为基础镜像(base image)。最后,当

一个镜像启动容器时,Docker会在该镜像的最顶层加载一个读写文件系统。在Docker中运行的

程序就是在这个读写层中执行的。

当Docker第一次启动一个容器时,初始的读写层是空的。当文件系统发生变化时,这些变

化都会应用到这一层上。比如,如果想修改一个文件,这个文件首先会从该读写层下面的只读

层复制到该读写层。该文件的只读版本依然存在, 但是已经被读写层中的该文件副本所隐藏。

通常这种机制称为写时复制(copy on write)。

可写容器
镜像

加入Apache

镜像

加入emacs

基础镜像

Ubuntu

引导文件系统

容器组、命名空间、设备映射

内核
图:Docker文件系统层
4.2 列出镜像

-->docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
imported container 1e48c825c36d 9 minutes ago 188.1 MB
ubuntu latest 8251da35e7a7 5 days ago 188.3 MB
centos 6.6 8b44529354f3 3 months ago 202.6 MB
注意:本地镜像都保存在Docker宿主机的/var/lib/docker目录下。每个镜像都保存在Docker所采用的

存储驱动目录下面,如aufs或者devicemapper。也可以在/var/lib/docker/containers目录下面看到所有的

容器。

-->ls /var/lib/docker/

aufs containers graph init linkgraph.db repositories-aufs tmp trust volumes

-->ls /var/lib/docker/aufs/ #ubuntu

diff layers mnt

-->ls /var/lib/docker/devicemapper/

devicemapper metadata mnt
-->ls /var/lib/docker/containers/

6e7c110c089da69721796358a68b520b8b16421d67d03a50260eff5929743d69 c3feb57d614438c5ad0f27868671c1fb70a55686292930f20e35b69b4cb4c24b

镜像从仓库下载下来。镜像保存在仓库中,而仓库存在于Registry中。默认的Registry是由Docker公司运营的

公共Registry服务,即Docker Hub。

提示:Docker Registry的代码是开源的,也可以运行自己的私有Registry。 https://hub.docker.com/

。查看ubuntu仓库中的其它镜像

-->docker pull ubuntu #表示通过docker pull命令来拉取ubuntu仓库中的所有内容。

latest: Pulling from ubuntu
6071b4945dcf: Pull complete
5bff21ba5409: Pull complete
e5855facec0b: Pull complete
8251da35e7a7: Pull complete
Digest: sha256:1572e29178048ad9ab72e78edd4decc91a3d8a8dea0ca39817efc7cf2d86c6d7
Status: Downloaded newer image for ubuntu:latest
-->docker images #查看仓库中的镜像

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
debian latest 9a61b6b1315e 9 days ago 125.2 MB
注意:虽然称其为Ubuntu操作系统,但实际上它并不是一个完整的操作系统。它只是一个裁剪板,只包含最低限度

的支持系统运行的组件。

为了区分同通一个仓库中的不同镜像,Docker提供了一种称为标签的功能。每个镜像在列出来时都带有一个标签,

如12.10、12.04、quantal等。每个标签对组成特定镜像的一些镜像层进行标记。这种机制使得在同一个仓库中可以存储

多个镜像。

可以通过在仓库名后面加上一个冒号和标签名来指定仓库中的某一镜像。

。运行一个带标签的Docker镜像。

-->docker run -t -i --name new_container ubuntu:12.04 /bin/bash

在构建容器时指定仓库的标签也是一个很好的习惯。这样可以准确地指定容器来源于哪里。

Docker Hub中有两种类型的仓库:用户仓库(user repository)和顶层仓库(top-level repository)。

用户仓库的镜像都是由Docker用户创建的,而顶层仓库则是由Docker内部的人来管理的。

用户仓库的命名由【用户名】和【仓库】两部分组成,如jamtur01/puppet

。 用户名:jamtur01

。 仓库名:puppet

与之相对,顶层仓库只包含仓库名部分,如ubuntu仓库。顶层仓库由Docker公司和由选定的能提供优质

基础镜像的厂商管理,用户可以基于这些基础镜像构建自己的镜像。同时顶层仓库也代表了各厂商和Docker

公司的一种承诺,即顶层仓库中的镜像是架构良好、安全且最新的。
4.3 拉取镜像

用docker run命令从镜像启动一个容器时,如果该镜像不在本地,Docker会先从Docker Hub下载该镜像。

如果没有指定具体的镜像标签,那么Docker会自动下载latest标签的镜像。例如,如果本地宿主机上还没有

ubuntu:latest镜像会将该镜像下载下来。

-->sudo docker run -t -i --name next_container ubuntu /bin/bash

Unable to find image 'ubuntu:latest' locally
latest: Pulling from ubuntu
83e4dde6b9cf: Downloading [> ] 327.2 kB/65.79 MB
83e4dde6b9cf: Download complete
b670fb0c7ecd: Download complete
29460ac93442: Download complete
d2a0ecffe6fa: Download complete
Status: Downloaded newer image for ubuntu:latest
可以通过docker pull命令自己来预先拉取镜像到本地。使用docker pull命令可以节省从一个新镜像启动

一个容器所需的时间。

。拉取一个fedora基础镜像

-->sudo docker pull fedora
可以使用docker images命令看到这个新镜像已经下载到本地Docker宿主机上了。

只查看fedora镜像的内容,可以通过docker images命令后面指定镜像名来实现。

-->sudo docker images fedora
7
可以看到,fedora镜像包括了开发版的Rawhide发布版以及Fedora 20,而且Fedora 20发布版是用来3个不同的

标签,即-- 20、heisenbug和latest --,但他们都是同一个镜像。因此,如果想使用Fedora 20镜像,可以使用下

面任意一种方式。

。fedora:20

。fedora:heisenbug

。fedora:latest

也可以使用docker pull命令拉取指定标签的镜像。

-->sudo docker pull fedora:20

该命令只会拉取fedora:20镜像
4.4 查找镜像

通过docker search命令来查找所有Docker Hub上公共的可用镜像。

-->sudo docker search puppet

提示:也可以在Docker Hub网站上在线查找可用镜像。
上面的命令在Docker Hub上查找了所有带有puppt的镜像。这条命令会完成镜像查找工作,并返回

如下信息:

* 仓库名;

* 镜像描述;

* 用户评价(Start) ---反应出一个镜像的受欢迎程度;

* 是否官方(Official) ---由上游开发者管理的镜像(如fedora镜像由Fedora团队管理);

* 自动构建(Automated)--表示这个镜像是由Docker Hub的自动构建(Automated Build)流程创建的。

从上面的结果中拉取一个镜像

-->sudo docker pull jamtur01/puppetmaster

这条命令将会下载jamtur01/puppetmaster镜像到本地(这个镜像里预装了Puppet master)。

用镜像构建一个容器

-->sudo docker run -i -t jamtur01/puppetmaster /bin/bash

-->root@722de8868486:/# facter
architecture => amd64
augeasversion => 1.2.0
blockdevice_fd0_size => 0
blockdevice_sda_model => VMware Virtual S
blockdevice_sda_size => 107374182400
..................................................................
可以看到,已经从jamtur01/puppetmaster镜像启动了一个新容器,以交互的方式启动了该容器,并且

在里面运行了Bash shell。在进入容器shell之后,运行了Facter (Puppet的主机探测应用),它也是预安装

在镜像之内的。最后,在容器里,运行了puppet程序以验证Puppet是否安装正常。
4.5 构建镜像

构建Docker镜像有以下两种方法:

。使用docker commit命令。

。使用docker build命令和Dockerfile文件

推荐使用Dockerfile构建Docker镜像。

注意:一般来说,不是真正“创建”新镜像,而是基于一个已有的基础镜像,如ubuntu或fedora等,构建

新镜像而已。如果真的想从零构建一个全新的镜像,可参考:https://docs.docker.com/articles/baseimages/

4.5.1 创建Docker Hub账号

可以将镜像推送到Docker Hub或者用户自己的私有Registry中,需要在Docker Hub上创建一个是账户,

可以从https://hub.docker.com/account/signup/加入Docker Hub。
登录:

-->docker login

Username: linux99199
Password:
Email: yhq72315@163.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
这条命令将户完成登录到Docker Hub的工作,并将认证信息保存起来以供后面使用。

注意:你的个人信息将会保存到$HOME/.dockercfg文件中

-->more /root/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "bGludXg5OTE5OTpfa2FpdHVvXyFAI18xMTAwOA==",
"email": "yhq72315@163.com"
}
}
}

4.5.2 用Docker的commit命令创建镜像

创建Docker镜像的第一种方法是使用docker commit命令,先创建一个容器,并在容器里做出修改,就像

修改代码一样,最后再将修改提交为一个新镜像。

先从创建一个新容器开始,这个容器基于之前的ubuntu镜像:

-->sudo docker run -i -t ubuntu /bin/bash

-->root@956e3d862ee2:/#
。在容器中安装Apache:

-->apt-get update #ubuntu

-->apt-get -y install apache2

将当前状态保存下来,这样就不必每次都创建一个新容器并再次在里面安装Apache了。

退出容器,再运行docker commit命令

-->exit

-->docker commit 4aab3ce3cb76 jamtur01/apache2

获取刚创建的容器的ID,以及一个目标镜像仓库和镜像名:

-->docker ps -l -q

-->docker image jamtur01/apache2

注意:docker commit提交的只是创建容器的镜像与容器当前状态之间有差异的部分,这使得该更新非常轻量。
。在提交镜像时指定更多的数据来详细描述所做的修改。

-->docker commit -m="A new custom image" --author="James Turnbull" ID号 jamtur01 /apache2:webserver

参数说明:

-m:用来指定新创建的镜像的提交信息。

-author选项:用来列出该镜像的作者信息

jamtur01/apache2:指定了镜像的用户名和仓库名,并为该镜像增加了一个webserver标签。
。查看镜像的详细信息

-->docker inspect

提示:可以从http://docs/docker.com/reference/commandline/cli/#commit 查看docker commit命令的所有选项。
如果想从刚创建的新镜像运行一个容器:

-->docker run -t -i jamtur01/apache2:webserver 来指定这个镜像
4.5.3 用Dockerfile构建镜像

并不推荐使用docker commit的方法来构建镜像。相反,推荐使用被称为Dockerfile的定义文件和docker build命令来

构建镜像。Dockerfile使用基本的基于DSL语法的指令来构建一个Docker镜像,之后使用docker build命令基于该Dockerfile

中的指令构建一个新的镜像。

。第一个Dockerfile

创建一个目录并在里面创建初始的Dockerfile,将创建一个包含简单Web服务器的Docker镜像。

-->mkdir /static_web

-->cd static_web

-->touch Dockerfile

Dockerfile为构建环境,Docker则称此环境为上下文或者构建上下文。Docker会在构建时将镜像构建上下文和该上下文

中的文件和目录上传到Docker守护进程。这样,Docker守护进程就能直接访问你想在镜像中存储的任何代码、文件或者其他

数据。

-->vim Dockerfile
# 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

运行:docker built -t Dockerfile

其它:

-->docker build -t ubuntu2 . #ubuntu2为镜像名,后面跟一个.

-->docker images 查看

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu2 latest 4d3aa407cc86 33 seconds ago 227.7 MB
ubuntu latest 7a608df676c8 2 days ago 188.4 MB
<none> <none> 91e54dfb1179 3 days ago 188.4 MB
registry latest 34a912ef9c03 10 days ago 423.3 MB
devopsil/puppetmaster latest de03fd6ba7d3 12 days ago 264.3 MB
debian latest 9a61b6b1315e 5 weeks ago 125.2 MB
<none> <none> d2a0ecffe6fa 6 weeks ago 188.4 MB
jamtur01/puppetmaster latest 99200e07340a 14 months ago 312.3 MB

发现已经创建了ubuntu2镜像。

该Dockerfile由一系列指令和参数组成。每条指令,如FROM,都必须为大写字母,且后面要跟随一个参数:

FROM ubuntu:14.04。 Dockerfile 中的指令会按顺序从上到下执行,所以根据需要合理安排指令的顺序。

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

。Docker从基础镜像运行一个容器。

。执行一条指令,对容器做出修改。

。执行类似docker commit的操作,提交一个新的镜像层。

。Docker再基于刚提交的镜像运行一个新容器。

。执行Dockerfile中的下一条指令,直到所有指令都执行完毕。
注意:Dockerfile也支持注释,以#开头的行都会被认为是注释。

内容说明:

FROM: 每个Dockerfile的第一条指令都应该是FROM。FROM指令指定一个已经存在的镜像,后续指令都将基于该镜像进行,

这个镜像被称为基础镜像(base image)。

MAINTAINER指令:这条指令告诉Docker该镜像的作者是谁,以及作者的电子邮件地址,这有助于标识镜像的所有者

和联系方式。

RUN指令会在当前的镜像中运行指定的命令。每条RUN指定都会创建一个新的镜像层,如果该指令执行成功,就会将

此镜像层提交,之后继续执行Dockerfile中的下一条指令。

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

不希望在shell中运行,也可以使用exec格式的RUN指令。

RUN [ "apt-get", " install", "-y", "nginx" ]

这种方式中,使用一个数组来指定要运行的命令和传递给命令的每个参数。

接着设置了EXPOSE指令,这条指令告诉Docker该容器内的应用程序将会使用容器的指定端口。这并不意味着可以自动

访问任意容器运行中的服务的端口(这里是80)。处于安全的原因,Docker并不会自动打开该端口,而是需要你在使用

docker run运行容器时来指定需要打开哪些端口。

可以指定多个EXPOSE指令来向外部公开多个端口。

注意:Docker也使用EXPOSE指令来帮助将多个容器链接。
4.5.4 基于Dockerfile构建新镜像

执行docker build命令时,Dockerfile中的所有指令都会被执行并且提交,并且在该命令成功结束后返回一个新镜像。

-->cd /static_web/

-->docker build -t="iso2/static_web" . #注意后面后一个.

Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> 7a608df676c8
Step 1 : MAINTAINER James Turnbull "james@example.com"
---> Using cache
---> e9661c5d0b2e
Step 2 : RUN apt-get update
---> Using cache
---> 070a6b8934df
Step 3 : RUN apt-get install -y nginx
---> Using cache
---> 1e91b4abfda3
Step 4 : EXPOSE 80
---> Using cache
---> 4d3aa407cc86
Successfully built 4d3aa407cc86

使用了docuer build命令来构建新镜像。

-t:为镜像设置了仓库和名称,本例中仓库为iso2,镜像名为static_web #名称随意
查看:

-->docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu2 latest 4d3aa407cc86 19 minutes ago 227.7 MB
iso2/static_web latest 4d3aa407cc86 19 minutes ago 227.7 MB
ubuntu latest 7a608df676c8 2 days ago 188.4 MB
<none> <none> 91e54dfb1179 3 days ago 188.4 MB
registry latest 34a912ef9c03 10 days ago 423.3 MB
devopsil/puppetmaster latest de03fd6ba7d3 12 days ago 264.3 MB
debian latest 9a61b6b1315e 5 weeks ago 125.2 MB
<none> <none> d2a0ecffe6fa 6 weeks ago 188.4 MB
jamtur01/puppetmaster latest 99200e07340a 14 months ago 312.3 MB

发现已经创建了名为iso2/static_web的镜像。

。在构建镜像的过程中为镜像设置一个标签,其使用方法为“镜像名:标签”

-->docker build -t="jamtur01/static_web:v1" .

Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> 7a608df676c8
Step 1 : MAINTAINER James Turnbull "james@example.com"
---> Using cache
---> e9661c5d0b2e
Step 2 : RUN apt-get update
---> Using cache
---> 070a6b8934df
Step 3 : RUN apt-get install -y nginx
---> Using cache
---> 1e91b4abfda3
Step 4 : EXPOSE 80
---> Using cache
---> 4d3aa407cc86
Successfully built 4d3aa407cc86
提示:如果没有指定任何标签,Docker将会自动为镜像设置一个latest标签。

上面命令告诉Docker到本地目录中去找Dockerfile文件,也可以指定一个Git仓库的源地址来指定

Dockerfile文件。也可以指定一个Git仓库的源地址来指定Dockerfile的位置。

-->docker buile -t="jamtur01/static_web:v1" git@github.com:jamtur01/docker-static_web

这里Docker假设在这个Git仓库的根目录下存在Dockerfile文件,再回到docker build过程,可以看到

构建上下文已经上传到了Docker守护进程。

提示:

如果在构建上下文的根目录下存在以.dockerignore命名的文件的话,那么该文件内容会被按行进行分割,

每一行都是一条文件过滤匹配模式。这非常像.gitignore文件,该文件用来设置哪些文件不会被上传到构建

上下文中去。该文件中模式的匹配规则采用了Go语言中的flepath。

之后,可以看到Dockerfile中的每条指令会被顺序执行,而且作为构建过程的最终结果,返回了新镜像的ID,

即4d3aa407cc86。构建的每一步及其对应指令都会独立运行,并且在输出最终镜像ID之前,Docker会提交每步的

构建结果。

4.5.5 指令失败时会怎样
比如将nginx写成ngin,执行:

-->docker build -t="jamtur01/static_web" .
需调试失败,用docker run命令来基于这次构建到目前为止已经成功的最后一步创建一个容器:

-->docker run -t -i 4d3aa407cc86 /bin/bash

在容器中再次调试:

-->apt-get install -y nginx #指定正确的包名

通过进一步调试找出到底是哪里出错,一旦解决了这个问题,就可以退出容器,使用正确的包名修改Dockerfile

文件,之后再尝试进行构建。
4.5.6 Dockerfile和构建缓存

Docker构建镜像会像之前的镜像层看做缓存,再次构建时会直接跳过前面的花缓存。
要想略过缓存功能,可以使用docker build的--no-cache标识。

-->docker build --no-cache -t="jamtur01/static_web" .
4.5.7 基于构建缓存的Dockerfile模板

构建缓存好处:可以实现简单的Dockerfile模板

比如在Dockerfile文件顶部使用相同的指令集模板。

FROM ubuntu:14.04

MAINTAINER James Turnbull "james@example.com"

ENV REFRESHED_AT 2015-08-24

RUN apt-get -qq update
运行:

-->docker built -t Dockerfile
分析:通过FROM指令为新镜像设置了一个基础镜像ubuntu:14.04,

然后使用MAINTAINER指令条件了自己的详细联系信息。

用ENV在镜像中设置名称为REFRESHED_AT的环境变量。这个环境表里用来表名该镜像模板

最后的更新时间。

最后,使用RUN指令来运行apt-get -qq update命令。该指令运行时将会刷新APT包的缓存,

用来确保能将要安装的每个软件包都更新到最新版本。
有了这个模板,如果想刷新一个构建,只需修改ENV指令中的日期。这使Docker在命中ENV指令

时开始重置这个缓存,并运行后续指令而无需依赖该缓存,即RUN apt-get update这条指令将会被再次

执行,包缓存也将会被刷新为最新内容,可以扩展此模板,比如适配到不同的平台或者添加额外的需求。
。构建支持fedora镜像,只需修改为如下:
FROM fedora:20

MAINTAINER James Turnbull "james@example.com"

ENV REFRESHED_AT 2014-07-01

RUN yum -y -q upgrade
4.5.8 查看新镜像
-->docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
jamtur01/static_web latest 524b4b0bc59a 14 seconds ago 227.7 MB
ubuntu2 latest 4d3aa407cc86 3 hours ago 227.7 MB
iso2/static_web latest 4d3aa407cc86 3 hours ago 227.7 MB
jamtur01/static_web v1 4d3aa407cc86 3 hours ago 227.7 MB
ubuntu latest 7a608df676c8 2 days ago 188.4 MB
<none> <none> 91e54dfb1179 3 days ago 188.4 MB
registry latest 34a912ef9c03 10 days ago 423.3 MB
devopsil/puppetmaster latest de03fd6ba7d3 13 days ago 264.3 MB
debian latest 9a61b6b1315e 5 weeks ago 125.2 MB
<none> <none> d2a0ecffe6fa 6 weeks ago 188.4 MB
jamtur01/puppetmaster latest 99200e07340a 14 months ago 312.3 MB
。查看某个镜像

-->docker images jamtur01/static_web

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
jamtur01/static_web latest 524b4b0bc59a About a minute ago 227.7 MB
jamtur01/static_web v1 4d3aa407cc86 3 hours ago 227.7 MB
。查看镜像是如何构建的

-->docker history 524b4b0bc59a

IMAGE CREATED CREATED BY SIZE COMMENT
524b4b0bc59a 3 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
0884f60db22f 3 minutes ago /bin/sh -c apt-get install -y nginx 18.13 MB
cc61844ad3bc 6 minutes ago /bin/sh -c apt-get update 21.18 MB
94dbc59fd234 19 minutes ago /bin/sh -c #(nop) MAINTAINER James Turnbull " 0 B
7a608df676c8 2 days ago /bin/bash 115 B Message
8251da35e7a7 2 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
e5855facec0b 2 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
5bff21ba5409 2 weeks ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
6071b4945dcf 2 weeks ago /bin/sh -c #(nop) ADD file:8c057200590b935e07 188.2 MB

4.5.9 从新镜像启动容器

。基于新构建的镜像启动一个新容器

-->docker run -d -p 80 --name static_web ubuntu2 nginx -g "daemon off;"

8c558f0e954bb8a2050c704172fa3854200fa0804dc9a21975bed4c8b1988313

参数说明:

. static_web:为容器名

. -d: 告诉Docker以分离的方式在后台运行。

. nginx -g "daemon off;": 以前台运行的方式启动Nginx,来作为Web服务器。

. -p:用来控制Docker在运行时应该公开哪些网络给外部(宿主机)端口。
Docker可以通过两种方法来在宿主机上分配端口。

1>Docker可以在宿主机上随机选择一个位于49000~49900的一个比较大的端口号来映射到容器中的

80端口上。

2>可以在Docker宿主机中指定一个具体的端口号来映射到容器中的80端口上。
。查看Docker容器端口分配情况

-->docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c558f0e954b ubuntu2 "nginx -g 'daemon of 6 minutes ago Up 6 minutes 0.0.0.0:32768->80/tcp static_web
85ba0d9c41b6 ubuntu "/bin/sh" 10 days ago Restarting (0) About an hour ago next_container2
6e7c110c089d debian "/bin/sh" 4 weeks ago Restarting (0) About an hour ago c3feb57d6144

可以发现,容器中的80端口被映射到了宿主机的32768上,可以通过docker port来查看容器的端口映射情况。

-->docker port 8c558f0e954b 80

0.0.0.0:32768

该命令返回了宿主机中映射的端口,即49154
。通过-p选项管理容器和宿主机之间的端口映射关系,可以指定将容器中的端口映射到Docker宿主机的某一特定端口上。

-->docker run -d -p 80:80 --name Ubuntu2 ubuntu2:latest nginx -g "daemon off;"

49e3bb7dc8b44d34f123ef52f389fe63366ebf52904aa4ef569778230e2a1216

上面的命令会将容器内的端口Ubuntu2(新的容器名称)的80端口绑定到本地主机(本地容器)ubuntu2:latest上面
。查看绑定后结果:

-->docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f99dcba9637d ubuntu2:latest "nginx -g 'daemon of 4 minutes ago Up 4 minutes 80/tcp, 0.0.0.0:8080->8080/tcp Ubuntu4
96063e5a40fd ubuntu2:latest "nginx -g 'daemon of 8 minutes ago Ubuntu3
49e3bb7dc8b4 ubuntu2:latest "nginx -g 'daemon of 12 minutes ago Up 12 minutes 0.0.0.0:80->80/tcp Ubuntu2
e6ad22c57129 ubuntu "nginx -g 'daemon of 15 minutes ago ubuntu2
8c558f0e954b ubuntu2 "nginx -g 'daemon of 32 minutes ago Up 32 minutes 0.0.0.0:32768->80/tcp static_web
。将端口绑定到不同的宿主机端口上去

-->docker run -d -p 8080:80 --name Ubuntu4 ubuntu2:latest nginx -g "daemon off;"

f99dcba9637ddbf19ee9130a63e0d1dc407705f4e956042728b223a17a1c7c4d

这条命令会将容器中的80端口绑定到宿主的8080端口上。
。将端口绑定限制在特定的网络接口(即IP地址)上

-->docker run -d -p 127.0.0.1:8089:8090 --name Ubuntu6 ubuntu2:latest nginx -g "daemon off;"

5d36d2f108d4c0b568f248b2a877f7340b79c332ab26f7669965a0a1a41865b7
表示将容器内的8090端口绑定在了本地宿主机的127.0.0.1这个IP的8089端口上。
。将容器内的80端口绑定到一个宿主机的随机端口上。

-->docker run -d -p 127.0.0.1::80 --name Ubuntu7 ubuntu2:latest nginx -g "daemon off;"

1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9
-->docker ps -a

1a84b1fe9453 ubuntu2:latest "nginx -g 'daemon of 22 seconds ago Up 21 seconds 127.0.0.1:32769->80/tcp Ubuntu7
或:

-->docker inspect 1a84b1fe9453
[
{
"Id": "1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9",
"Created": "2015-08-24T07:23:30.962862185Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"State": {
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 4007,
"ExitCode": 0,
"Error": "",
"StartedAt": "2015-08-24T07:23:31.229665837Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "4d3aa407cc8664e2c79f0df36b6caad3ce4ff8fbea3c3554e2b9f3d1054c49c8",
"NetworkSettings": {
"Bridge": "",
"EndpointID": "61182ff0deffd52f342561330061b3fc228f4a484893cac001ea00e19b3acde9",
"Gateway": "172.17.42.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"HairpinMode": false,
"IPAddress": "172.17.0.14",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:0e",
"NetworkID": "cb10be1ca99ad68a25ef3e430afcced66672ddb5b241905feb7c9b7d50581cec",
"PortMapping": null,
"Ports": {
"80/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": "32769"
}
]
},
"SandboxKey": "/var/run/docker/netns/1a84b1fe9453",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null
},
"ResolvConfPath": "/var/lib/docker/containers/1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9/hostname",
"HostsPath": "/var/lib/docker/containers/1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9/hosts",
"LogPath": "/var/lib/docker/containers/1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9/1a84b1fe9453623d4df160812995e94f276f6d6e358e61ba3f4831b5b5016bb9-json.log",
"Name": "/Ubuntu7",
"RestartCount": 0,
"Driver": "aufs",
"ExecDriver": "native-0.2",
"MountLabel": "",
"ProcessLabel": "",
"Volumes": {},
"VolumesRW": {},
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LxcConf": [],
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 0,
"CpuPeriod": 0,
"CpusetCpus": "",
"CpusetMems": "",
"CpuQuota": 0,
"BlkioWeight": 0,
"OomKillDisable": false,
"Privileged": false,
"PortBindings": {
"80/tcp": [
{
"HostIp": "127.0.0.1",
"HostPort": ""
}
]
},
"Links": null,
"PublishAllPorts": false,
"Dns": null,
"DnsSearch": null,
"ExtraHosts": null,
"VolumesFrom": null,
"Devices": [],
"NetworkMode": "bridge",
"IpcMode": "",
"PidMode": "",
"UTSMode": "",
"CapAdd": null,
"CapDrop": null,
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"SecurityOpt": null,
"ReadonlyRootfs": false,
"Ulimits": null,
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"CgroupParent": ""
},
"Config": {
"Hostname": "1a84b1fe9453",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"PortSpecs": null,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "ubuntu2:latest",
"Volumes": null,
"VolumeDriver": "",
"WorkingDir": "",
"Entrypoint": null,
"NetworkDisabled": false,
"MacAddress": "",
"OnBuild": null,
"Labels": {}
}
}
]
或:

-->docker port 1a84b1fe9453

80/tcp -> 127.0.0.1:32769

提示:也可以通过在端口绑定时使用/udp后缀来指定UDP端口

-P: 参数可以用来对外公开在Dockerfile中的EXPOSE指令中设置好的所有端口。
-->docker run -d -P --name Ubuntu8 ubuntu2:latest nginx -g "daemon off;"

4f2ec2583862f2f3c7bc9e6906fad575ec5972fe8eec07110093a4f2a10c8f66

该命令会将容器内的80端口对本地宿主机公开,并且绑定到宿主机的一个随机端口上。

该命令会将用来构建该镜像的Dockerfile文件中EXPOSE指令指定的其它端口也一并公开。
-->docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f2ec2583862 ubuntu2:latest "nginx -g 'daemon off 27 seconds ago Exited (1) 26 seconds ago Ubuntu8
有了这个端口,就可以使用本地宿主机的IP地址或者127.0.0.1的localhost连接到运行中的容器,查看Web服务器内容了。

注意:可以通过ifconfig或者ip addr命令来查看本地宿主机的IP地址

-->curl localhost:32769c

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a rel="nofollow" target="_blank" href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a rel="nofollow" target="_blank" href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
其实查看的是nginx主页

这样就得到了一个非常简单的基于Docker的Web服务器。

4.5.10 Dockerfile指令

可以在Dockerfile中放入更多其它指令,这些指令包括CMD、ENTRYPOINT、ADD、COPY、VOLUME、

WORKDIR、USER、ONBUILD和ENV等。

1.CMD

CMD指令用于指定一个容器启动时要运行的命令,类似RUN,只是RUN指令是指定镜像被构建时要运行的命令,

而CMD是指定容器被启动时要运行的命令。

-->docker run -i -t 4f2ec2583862 /bin/true

。采用CMD方式:

-->docker run -i -t 4f2ec2583862 CMD ["/bin/true"]

。CMD方式指定参数运行

-->docker run -i -t 4f2ec2583862 CMD ["/bin/true", "-l"]

这里将-l标志传递给了/bin/bash命令。
警告:

要运行的命令是存放在一个数组结构中的,这将告诉Docker按指定原样来运行该命令。当然也可以不使用数组时

指定CMD指令,这时候Docker会在指定的命令前加上/bin/;sh -c。这在执行该命令的时候可能导致意料之外的行为,

所以, Docker推荐一直使用以数组语法来设置要执行的命令。

使用Docker run命令可以覆盖CMD指令。如果在Dockerfile里指定了CMD指令,而同时在docker run命令行中也

指定了要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。
例:

Dockerfile

CMD [ "/bin/bash" ]

-->docker build -t Dockerfile
使用docker build命令构建一个新镜像,并给予此镜像启动一个新容器。

-->docker run -t -i ubuntu:latest

root@d1eecf5f33b0:/#
发现,在docker run命令的末尾并为指定要运行什么命令,。实际上,Docker使用了CMD指令中的指定的命令。

。指定要运行的命令

-->docker run -t -i ubuntu:latest /bin/ps

PID TTY TIME CMD
1 ? 00:00:00 ps

root@Ubuntu2:~#
看到,在这里指定了想要运行的命令/bin/ps,该命令会列出所有正在运行的进程。容器并没有启动shell,而

是通过命令行参数覆盖了CMD指令指定的命令,容器运行后列出了正在运行的进程的列表,之后停止了容器。
提示:Dockerfile中只能指定一条CMD指令。如果指定了多条CMD命令,也只有最有一条CMD指令会被使用。如果

想在启动容器时运行多个进程或者多条命令,可以考虑使用类似Supervisor这样的服务管理工具。
2.ENTRYPOINT

ENTRYPOINT指令与CMD指令非常类似。

希望容器按需要的那样去工作时候CMD就不太适合了。而ENTRYPOINT指令提供的命令不容易在启动容器时被覆盖。

实际上,docker run命令行中指定的任何参数都会被当作参数再次传递给ENTRYPOINT指令中指定的命令。

例:

ENTRYPPOINT ["/usr/sbin/nginx"]

可以在该指令中通过数组的方式为命令指定相应的参数。

ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

注意:从上面看到的CMD指令可以看到,通过以数组的方式提交ENTRYPPOINT在想运行的命令前加入/bin/sh -c来

避免各种问题。

重新构建镜像,并将ENTRYPOINT设置为ENTRYPOINT ["/usr/sbin/nginx"]

-->cd /static_web/

-->docker build -t="jamtur01/static_web" .

Sending build context to Docker daemon 3.072 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> 7a608df676c8
Step 1 : MAINTAINER James Turnbull "james@example.com"
---> Using cache
---> 94dbc59fd234
Step 2 : DOCKER
Unknown instruction: DOCKER
然后,从ubuntu2镜像启动一个新容器

-->docker build -t "

博主

让学习成为习惯,坚持-共享-开源-自由! 成功者决不放弃,放弃者绝不成功!

相关推荐

嗨、骚年、快来消灭0回复。