本文章翻译自Docker的官方教程,有兴趣的同学可以上Docker官网进行
play-with-docker
学习。Docker的安装教程请参考这里(未定义)
本文翻译自Docker官方教程
Doing More With Docker Images
,并作出一定的修改及删减以加快上手速度。
     Docker教程(二) – 将容器打包成Docker镜像、使用Dockerfile打包镜像
    
   通过上一个教程,我们已经学会了如何从
   
    Docker Store
   
   下载 Docker 镜像,并用这个镜像尝试创建了几个不同的容器。但是,只会这样创建容器是没有实际意义的,我们需要学会更多对镜像的操作技巧,从而在我们的实际工作过程中,起到省钱、省时的作用。
    尽管
    
     Docker Store
    
    上可以下载到各种各样的 Docker 镜像,但是,一些比较大的镜像(大于700k),就已经可能包含了许多你在你的实际应用环境中所不需要的东西,显然你并不希望直接使用这些
    
     非标准
    
    的镜像。所以,通常情况下,我们会下载一些比较
    
     标准
    
    的镜像,再添加一些我们自己所需要的东西,然后制作成为一个符合我们需求的镜像,这样以后我们就可以重用(re-use)并向其他人分享我们这个这个自定义的镜像。
   
    在这个教程中,我们会首先简单地用
    
     commit
    
    的方式将我们的一个容器制作成一个镜像。然后我们会学习使用更加高效,强大的方式:
    
     Dockerfile
    
    。
   
    
    
    将容器打包成镜像
   
    首先,我们使用交互模式打开一个
    
     ubuntu
    
    容器中的
    
     shell
    
    。
   
sudo docker container run -ti ubuntu bash
    这个 ubuntu 容器是一个标准的容器,现在让我们对其进行一个小修改,我们为它安装一个叫
    
     figlet
    
    的软件包。
   
FIGlet
是基于ASCII字符组成的字符画。具体可以参考
这里
。
sudo apt-get update
sudo apt-get install -y figlet
figlet "hello docker"
exit
    
    
    执行上面的指令,你会看见终端打印了一个很“酷炫”的 hello world 字符画。OK, 现在我们这个
    
     ubuntu + figlet
    
    的容器就已经准备好了。
   
    好了,现在你觉得这个
    
     figlet
    
    很有趣(不能觉得有趣,我不要你觉得),你想向你的朋友分享一下。当然,因为这个例子很简单,你可以直接告诉你的朋友怎样去安装这个。但是,如果这是一个很复杂的过程,你可能安装了很多软件包,甚至做了很多根本无法理解的配置,让你去写一个文档去说明怎样搞就显得很麻烦了。
   
    所以,你需要做的事是,将这个
    
     docker容器
    
    ,做成一个
    
     image镜像
    
    ,这样你只需要把这个镜像分享给你的朋友,他就可以用这个镜像构建出一个和你一模一样的容器来。
   
首先,查看一下现在我们有哪些容器。
sudo docker container ls -a
    
    
    可见,<CONTAINER_ID> 为
    
     d304e87568da
    
    的容器,就是我们刚才运行
    
     figlet
    
    的容器。你可以输入下面的命令看一下我们对这个容器做了哪些修改。
   
# example: sudo docker container diff d304e87568da
sudo docker container diff < 输入你的 CONTAINER_ID >
你会看到有一系列的文件被列出,这就是我们刚才所做的修改。
列出的是这个
当前这个容器
,和
使用镜像构建的原始容器
的不同
    现在,要生成一个
    
     ubuntu + figlet
    
    的镜像,你需要
    
     commit
    
    这个容器。这个
    
     commit
    
    的操作会在你的本地,根据你指定的容器,创建一个镜像。
   
# example: sudo docker container commit d304e87568da our_figlet:v0.1
sudo docker container commit < 输入你的 CONTAINER_ID > <需要构建的镜像名:版本号>
创建完后,在查看一下现在本地的镜像
sudo docker image ls
    
    这时,发现我们多了一个叫
    
     our_figlet
    
    ,版本号为
    
     v0.1
    
    的镜像。
    
    
    现在我们尝试一下用我们刚才新建的镜像来构建一个容器,并运行一下
    
     figlet
    
    :
   
sudo docker container run our_figlet:v0.1 figlet hello
    
    
    现在我们有了这个镜像,我们就能很轻松地构建多个相同的容器了。不过,这个镜像现在只是存在本地,你很难和你的朋友分享。你可以将这个镜像上传到服务器上,例如 DockerHub, 这样其他人就能很容易地使用到你的这个镜像。
   
    
    
    使用 Dockerfile 打包镜像
   
    除了直接创建静态的二进制的 docker 镜像外,我们还可以使用
    
     Dockerfile
    
    来创建镜像。当我们的镜像变得越来越大,越来越复杂的时候,使用
    
     Dockerfile
    
    来创建镜像,可以令你能更方便地管理你的镜像。
   
    用上面的
    
     figlet
    
    来举个例子,我们在上面创建的
    
     our_figlet
    
    镜像,使用的是我们当前最新版本(
    
     :latest
    
    )的
    
     figlet
    
    软件包。但是,在未来的某一天,
    
     figlet
    
    更新了,我们又想用最新版本的
    
     figlet
    
    ,这样,我们只能重复上面的步骤,重新创建一个新的镜像。如果你的镜像包含了9999999个这样要更新的软件包,这样做你就GG了。然而,如果你是使用
    
     Dockerfile
    
    来创建镜像的话,你仅需要在
    
     Dockerfile
    
    里面添加一行
    
     apt update
    
    ,就可以保证以后创建出来的镜像都包含最新的
    
     figlet
    
    。
   
    OK, 现在我们开始尝试用
    
     Dockerfile
    
    来创建一个镜像。
   
    首先,写一个简单的js程序,命名为
    
     index.js
    
    。
   
var os = require("os");
var hostname = os.hostname();
console.log("hello from " + hostname);
本人不懂JavaScript, 上面的程序是来自Docker官方教程,为保持统一,这里依然使用js程序,如果有理解错的地方欢迎指出。
这里应该是一个简单的Hello World程序。然后在相同目录下创建一个文件,文件名为Dockerfile,复制下面的内容:
FROM alpine
RUN apk update && apk add nodejs
COPY . /app
WORKDIR /app
CMD ["node","index.js"]
    准备好以后,执行以下命令,创建一个叫
    
     hello:v0.1
    
    的镜像。
   
sudo docker image build -t hello:v0.1 .		# 注意后面那个“.”,这个点表示当前目录
    构建这个
    
     Dockerfile
    
    相当于执行了以下操作:
   
- 
     下载一个标准的
 
 alpine
 
 镜像
- 用这个镜像构建一个容器
- 
     在这个容器里面运行
 
 apk update
 
 和
 
 apk add nodejs
 
- 
     将
 
 inde.js
 
 文件复制到容器的
 
 /app
 
 目录下
- 
     进入 /app目录,并执行
 
 node index.js
 
 指令
- 最后将这个容器构建成一个新的镜像
    
    现在查看一下我们本地所拥有的镜像并运行这个镜像:
   
sudo docker images
sudo docker run hello:v0.1
    
    
    可以看见,我们现在拥有一个版本号为
    
     v0.1
    
    的,名叫
    
     hello
    
    的镜像,运行的时候,终端会显示这个容器的ID。
   
容器的ID可以通过
sudo docker ps -a
来查看
    
    
    镜像的层
   
    
    
    镜像检查
   
 
