Dockerfile 使用基于DSL语法的指令来构建一个Docker镜像,之后使用docker build命令基于该Dockerfile的指令构建一个新的镜像。
关于DSL语言,博主仔细查阅了一下,有兴趣的可以参考郭晓刚老师翻译的《领域专用语言实战》http://book.51cto.com/art/201310/412336.htm
创建Dockerfile文件
我们必须创建一个目录来保存Dockerfile,这个目录被称为构建上下文(build context)。Docker会在构建镜像时将该上下文中的所有目录和文件都上传到Docker的守护进程,便于Docker直接访问你想在镜像中存储的所有代码、文件和数据等。
创建代码如下:
#mkdir static_web
#cd static_web
#vim Dockerfile
博主的Dockerfile文件如下:
Dockerfile指令详解
从这里也能看到我们Docker采用的“写时复制”的概念。这样的好处一方面是轻量化,另一方面就是即使中间某一个指令运行出错,我们也可以很方便的基于前一个运行完好的镜像进行调试,而且调试好之后不用再次运行前面已经运行好了的指令。
构建镜像代码如下:
docker build -t="zhangyang/static_web" .
-t 选项指定了创建新镜像的仓库名和镜像名。例如我的仓库名就是自己的名字zhangyang镜像名是static_web
最后的 .告诉Docker从当前目录去寻找Dockerfile文件,当然也可以指定一个Git的地址。
可以看到,最终返回了该镜像的ID b92c35890d8a
而且在每一个step运行完毕之后都会返回一个ID,即Docker会提交每一步的执行结果。
博主在这里把我的dockerfile文件的nginx故意错写为ngnx,然后build.报错如下:
我们可以看到,错误出在step4,而在step3结束之后就提交了一个新的镜像层e8ec593f1475
我们可以使用命令
docker run -i -t e8ec593f1475 /bin/bash
进入该容器进行调试,解决了该问题之后再退出容器修改Dockerfile文件相应的出错位置。
Docker将每一步结束之后提交的镜像层当作缓存。
然而有些时候我们必须确保之前的缓存被覆盖掉。例如,如果已经缓存了之前的第三步,即 apt-get update 但是我们必须确保接下来安装的软件是最新版本,那就必须忽略缓存功能。可以使用docker build 的–no-cache 标志。
docker build --no-cache -t="zhangyang/static_web" .
我们可以在Dockerfile文件中使用ENV指令来设置一个环境变量,此环境变量用来指明该模板最后的更新时间。
Dockerfile模板文件示例如下:
FROM Ubuntu14.04
MAINTAINER zhangyang "[email protected]"
ENV REFRESHED_AT 2014-07-01
RUN apt-get -qq update
博主在上述文件创建了一个环境变量REFRESHED_AT。
也就是说,在每次需要刷新构建的时候,只要修改ENV指令中的日期值就可以重置缓存,包缓存会被update成为最新值。
docker images zhangyang/static_web
docker history zhangyang/static_web
这条命令会显示镜像构建过程
此命令详细显示了镜像构建的每一层,以及其Docker指令
-p标志指定容器在运行时开放哪些端口给宿主机
-P(大写)标志将Dockerfile文件中的EXPOSE指定的端口全部开放
从新镜像启动一个容器:
docker run -d -p 80 --name static_web_2 zhangyang/static_web / nginx -g "daemon off;"
上述命令运行了一个名为static_web_2的新容器,选项-d是告诉Docker在后台以分离(detached)方式运行,这种模式非常适合nginx这样需要长时间运行的进程。最后我们还指定了在容器中需要运行的命令:nginx -g “daemon off;”。这将以前台的方式运行nginx来作为我们的服务器。
-p选项把80端口开放给了宿主机,Docker可以有两种模式来开放端口:
我们可以使用下面的命令来查看端口分配情况:
docker ps -l
也可以使用docker port ID 端口号
来查看被映射的宿主机上的具体端口号。
docker run -d -p 127.0.0.1:80:80 --name static_web_2 zhangyang/static_web \nginx -g "daemon off;"
也可以直接指定宿主机上的某一个端口映射给容器。但显然这样这能运行一个Docker不利于我们充分发挥Docker的优势。
如果非要指定宿主机的IP地址的话可以这样写:
docker run -d -p 127.0.0.1::80 --name static_web_2 zhangyang/static_web \nginx -g "daemon off;"
该命令会随机分配一个127.0.0.1上的端口映射到容器的80端口上