最小 Docker 鏡像 hello-world 剖析

 

開始學習 Docker 的同學基本上都是按照官方的 guide 來安裝,之後要測試是否已經安裝成功,官方會讓你 pull 一個 hello-world 示例鏡像下來並運行,如下命令:

 [email protected] ⮀ ~ ⮀ docker pull hello-world
31cbccb51277: Pull complete
e45a5af57b00: Pull complete
511136ea3c5a: Already exists
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Status: Downloaded newer image for hello-world:latest

guohl@ghl-MBP ⮀ ~ ⮀ docker run hello-world
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/

出現上面的輸出信息表示你 Docker 安裝成功。使用下面命令查看該鏡像的信息,發現大小隻有 910B:

[email protected] ⮀ ~ ⮀ docker images hello-world
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              e45a5af57b00        3 months ago        910 B

那麼該鏡像運行怎麼就輸出上面這一串信息的呢?如果對 Docker 瞭解一點的話自然會去找該鏡像的 Dockerfile,Dockerfile 詳細描述了該鏡像是如何建立的以及運行時執行的命令。從 Docker Hub 上 hello-world 的庫簡介 找到其 Dockerfile 在 github 上,簡簡單單的三條語句:

FROM scratch
ADD hello /
CMD ["/hello"]
  • 第一條FROM指令是 Docker 用來指定該鏡像是基於哪個基礎鏡像構建的,這裏指定爲 scratch,實際上 scratch 鏡像是一個空鏡像,用來構建基礎鏡像或者極小的鏡像。
  • 第二條ADD指令表示從 Dockerfile 所在目錄拷貝文件到指定路徑下,這裏拷貝 hello 文件到根目錄下,至於 hello 文件是什麼稍後介紹。
  • 第三條CMD指令用來指示當運行 docker run 命令運行該鏡像時要執行的命令,這裏執行 /hello,就是執行第二步拷貝到根目錄下的 hello 文件。

hello 是一個可執行的二進制文件,從文章的開頭可以推測該文件執行輸出那一堆提示信息,那該文件怎樣生成的呢?從 hello-world 的庫中可以看到還有兩個文件,一個是彙編文件 hello.asm,還有一個 Makefile 文件,可以猜測 hello 就是事先通過 hello.asm 編譯得到的,如 Makefile 文件所描述的編譯過程:

hello: hello.asm
    nasm -o $@ $<
    chmod +x hello

.PHONY: clean
clean:
    -rm -vf hello

該 Makefile 文件比較容易理解,主要是使用 nasm 彙編器將 hello.asm 編譯生成可執行文件 hello

最後再來看看 hello.asm 文件,這是一段 Intel x86 彙編:

; this is especially thanks to:
; http://blog.markloiseau.com/2012/05/tiny-64-bit-elf-executables/

BITS 64
    org 0x00400000  ; Program load offset

; 64-bit ELF header
ehdr:
    ;  1), 0 (ABI ver.)
    db 0x7F, "ELF", 2, 1, 1, 0       ; e_ident
    times 8 db 0                     ; reserved (zeroes)

    dw 2              ; e_type: Executable file
    dw 0x3e           ; e_machine:  AMD64
    dd 1              ; e_version:  current version
    dq _start         ; e_entry:    program entry address (0x78)
    dq phdr - $$      ; e_phoff   program header offset (0x40)
    dq 0              ; e_shoff no section headers
    dd 0              ; e_flags no flags
    dw ehdrsize       ; e_ehsize:   ELF header size (0x40)
    dw phdrsize       ; e_phentsize:    program header size (0x38)
    dw 1              ; e_phnum:    one program header
    dw 0              ; e_shentsize
    dw 0              ; e_shnum
    dw 0              ; e_shstrndx

ehdrsize equ $ - ehdr

; 64-bit ELF program header
phdr:
    dd 1              ; p_type: loadable segment
    dd 5              ; p_flags read and execute
    dq 0              ; p_offset
    dq $$             ; p_vaddr:	start of the current section
	dq $$             ; p_paddr: "       "
    dq filesize       ; p_filesz
    dq filesize       ; p_memsz
    dq 0x200000       ; p_align:    2^11=200000 = section alignment

; program header size
phdrsize equ $ - phdr

; Hello World!/your program here
_start:

    ; sys_write(stdout, message, length)
    mov rax, 1           ; sys_write
    mov rdi, 1           ; stdout
    mov rsi, message     ; message address
    mov rdx, length      ; message string length
    syscall

    ; sys_exit(return_code)
    mov rax, 60          ; sys_exit
    mov rdi, 0           ; return 0 (success)
    syscall

    message:
        db 'Hello from Docker.', 0x0A
        db 'This message shows that your installation appears to be working correctly.', 0x0A
        db 0x0A
        db 'To generate this message, Docker took the following steps:', 0x0A
        db ' 1. The Docker client contacted the Docker daemon.', 0x0A
        db ' 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.', 0x0A
        db '    (Assuming it was not already locally available.)', 0x0A
        db ' 3. The Docker daemon created a new container from that image which runs the', 0x0A
        db '    executable that produces the output you are currently reading.', 0x0A
        db ' 4. The Docker daemon streamed that output to the Docker client, which sent it', 0x0A
        db '    to your terminal.', 0x0A
        db 0x0A
        db 'To try something more ambitious, you can run an Ubuntu container with:', 0x0A
        db ' $ docker run -it ubuntu bash', 0x0A
        db 0x0A
        db 'For more examples and ideas, visit:', 0x0A
        db ' http://docs.docker.com/userguide/', 0x0A
    length: equ $-message            ; message length calculation

; File size calculation
filesize equ $ - $$

也比較簡單,就調用了兩個系統調用,sys_write 向標準輸出打印一段信息,sys_exit 退出程序。

至此,我們分析完了官方提供的 hello-world 鏡像整個構建及運行過程,麻雀雖小,五臟俱全,理解最小的 Docker 鏡像的工作機制對我們理解 Docker 有很大幫助。

CentOS 6/7系列安裝Docker http://www.linuxidc.com/Linux/2014-07/104768.htm 

Docker的搭建Gitlab CI 全過程詳解 http://www.linuxidc.com/Linux/2013-12/93537.htm 

Docker安裝應用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm 

在 Docker 中使用 MySQL http://www.linuxidc.com/Linux/2014-01/95354.htm

在Ubuntu Trusty 14.04 (LTS) (64-bit)安裝Docker http://www.linuxidc.com/Linux/2014-10/108184.htm 

Docker安裝應用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm 

Ubuntu 14.04安裝Docker  http://www.linuxidc.com/linux/2014-08/105656.htm 

阿里雲CentOS 6.5 模板上安裝 Docker http://www.linuxidc.com/Linux/2014-11/109107.htm 

Docker 的詳細介紹請點這裏
Docker 的下載地址請點這裏

本文永久更新鏈接地址http://www.linuxidc.com/Linux/2015-04/116554.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章