### 什么是Docker 鏡像
Image 是一個可運行的基本單元,那么當我們運行 docker images 時,顯示出來的一個個 image 究竟是什么?
Image 里面是一層層文件系統,叫做 Union FS,聯合文件系統,可以將幾層目錄掛載到一起,成為同一個虛擬文件系統。文件系統的目錄結構就像普通 linux 的目錄結構一樣,docker 通過這些文件與宿主機的內核提供了一個 linux 的虛擬環境。每一層文件系統我們叫做一層 layer,聯合文件系統可以對每一層文件系統設置三種權限,只讀(readonly)、讀寫(readwrite)和寫出(whiteout-able),但是 docker 鏡像中每一層文件系統都是只讀的。
構建鏡像的時候,從一個最基本的操作系統開始,每個構建的操作都相當于做一層修改,增加了一層文件系統,一層層往上疊加,上層的修改會覆蓋底層該位置的可見性,這也很容易理解,就像上層把底層遮住了一樣。當你使用的時候,你只會看到一個完全的整體,你不知道里面有幾層,也不清楚每一層所做的修改是什么。結構類似這樣:

[Docker images參考資料](http://blog.csdn.net/jcjc918/article/details/46500031)
查看鏡像
docker images
拉取Ubuntu 鏡像
docker pull Ubuntu:12.04
查找鏡像
docker search puppet
### 構建鏡像
構建docker 鏡像主要有以下兩種方法:
- 使用docker commit
- 使用docker build 命令和dockerfile
#### 用 Docker的commit 命令創建鏡像
創建一個需要修改的新容器
docker run -it centos /bin/bash
yum install httpd -y
docker commit 3eb63f380ffc ttlinux/httpd
查看創建的鏡像
[root@ttlinux ~]# docker images ttlinux/httpd
REPOSITORY TAG IMAGE ID CREATED SIZE
ttlinux/httpd latest f530ece34d7e About a minute ago 309MB
### 使用dockerfile 構建鏡像
我們的第一個Dockerfile
FROM centos:7.4.1708
MAINTAINER James Turnbull "james@example.com"
RUN yum install -y epel-release && \
yum install -y nginx && \
echo 'Hi, I am in your container' \
> /usr/share/nginx/html/index.html
EXPOSE 80
基于Dockerfile 構建新鏡像
docker build -t="ttlinux/static_web" .
在構建時為鏡像設置標簽
docker build -t="ttlinux/static_web:v1" .
忽略Dockerfile的緩存構建
docker build --no-cache -t="ttlinux/static_web" .
基于構建緩存的Dockerfile 模板
FROM ubuntu:16.04
MAINTAINER James Turnbull "james@example.com"
ENV REFRESHED_AT 2016-06-01
RUN apt-get -qq update
Docker build的注意點
如果接觸過Docker,Docker build大家都清楚怎么用了,但是有幾個容易忽略的注意點:
1. Dockerfile開頭的 From 和 MAINTAINER 其實都是一層鏡像
1. 如果 From 和 MAINTAINER 不同,就算是后面的命令語句相同也不會是相同的鏡像。如都是執行 RUN echo "hello world" >> test.txt ,如果 MAINTAINER 不同,則生成的這個語句的鏡像層將是不同的。
1. 原理上如果每一層對應的父層不同,那怕執行的命令相同,Docker也會生成一層新的鏡像,如下面兩個Dockerfile文件
查看新鏡像
docker images ttlinux/static_web
docker history ttlinux/static_web
IMAGE CREATED CREATED BY SIZE COMMENT
9b8143f32f0c 36 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
07529562454c 36 minutes ago /bin/sh -c echo 'Hi, I am in your containe... 27B
013baaf856e2 36 minutes ago /bin/sh -c apt-get install -y nginx 56.5MB
462e7a046c42 39 minutes ago /bin/sh -c apt-get update 39.2MB
a8ff8f7ace1f 41 minutes ago /bin/sh -c #(nop) MAINTAINER James Turnbu... 0B
dd6f76d9cc90 10 days ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 10 days ago /bin/sh -c mkdir -p /run/systemd && echo '... 7B
<missing> 10 days ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\... 2.76kB
<missing> 10 days ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B
<missing> 10 days ago /bin/sh -c set -xe && echo '#!/bin/sh' >... 745B
<missing> 10 days ago /bin/sh -c #(nop) ADD file:5b334adf9d9a225... 122MB
從新鏡像啟動一個容器
docker run -d -p 82:80 --name static_web ttlinux/static_web nginx -g "daemon off;"
docker run -d -p 127.0.0.1:82:80 --name static_web ttlinux/static_web nginx -g "daemon off;"
docker run -d -P --name static_web ttlinux/static_web nginx -g "daemon off;"
### Dockerfile指令
#### 一.Dockerfile 基本結構
一般的,Dockerfile 分為四部分:基礎鏡像信息、維護者信息、鏡像操作指令和容器啟動時執行指令。’#’ 為 Dockerfile 中的注釋。先看下面一個小例子:
# This my first nginx Dockerfile
# Version 1.0
# Base images 基礎鏡像
FROM centos
#MAINTAINER 維護者信息
MAINTAINER tianfeiyu
#ENV 設置環境變量
ENV PATH /usr/local/nginx/sbin:$PATH
#ADD 文件放在當前目錄下,拷過去會自動解壓
ADD nginx-1.8.0.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/
#RUN 執行以下命令
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www
#WORKDIR 相當于cd
WORKDIR /usr/local/nginx-1.8.0
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install
RUN echo "daemon off;" >> /etc/nginx.conf
#EXPOSE 映射端口
EXPOSE 80
#CMD 運行以下命令
CMD ["nginx"]
FROM : 指定基礎鏡像,要在哪個鏡像建立
格式為 FROM <image> 或FROM <image>:<tag> 。
第一條指令必須為 FROM 指令。
MAINTAINER:指定維護者信息
格式為 MAINTAINER <name>
RUN:在鏡像中要執行的命令
格式為 RUN <command> 或 RUN ["executable", "param1", "param2"]
前者將在 shell 終端中運行命令,即 /bin/bash -c ;后者則使用 exec 執行。指定使用其它終端可以通過第二種方式實現,例如 RUN [“/bin/bash”, “-c”,”echo hello”] 。
WORKDIR:指定當前工作目錄,相當于 cd
格式為 WORKDIR /path/to/workdir
為后續的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目錄。
可以使用多個 WORKDIR 指令,后續命令如果參數是相對路徑,則會基于之前命令指定的路徑。例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑為 /a/b/c 。
EXPOSE:指定容器要打開的端口
格式為 EXPOSE <port> [<port>...]
告訴 Docker 服務端容器暴露的端口號,供互聯系統使用。在啟動容器時需要通過 -P,Docker 主機會自動分配一個端口轉發到指定的端口。
ENV:定義環境變量
格式為 ENV <key> <value> 。 指定一個環境變量,會被后續 RUN 指令使用,并在容器運行時保持。
例如
ENV PATH /usr/local/nginx/sbin:$PATH
COPY :復制本地主機的 (為 Dockerfile 所在目錄的相對路徑)到容器中的
格式為 COPY 。
ADD:相當于 COPY,但是比 COPY 功能更強大
格式為 ADD <src> <dest>
該命令將復制指定的 到容器中的 。 其中 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件,復制進容器會自動解壓。
VOLUME:掛載目錄
格式為VOLUME ["/data"]
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。
USER
格式為 USER daemon
指定運行容器時的用戶名或 UID,后續的 RUN 也會使用指定用戶。當服務不需要管理員權限時,可以通過該命令指定運行用戶。并且可以在之前創建所需要的用戶,例如: RUN useradd -s /sbin/nologin -M www。
ENTRYPOINT
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中執行)
配置容器啟動后執行的命令,并且不可被 docker run 提供的參數覆蓋。每個 Dockerfile 中只能有一個 ENTRYPOINT ,當指定多個時,只有最后一個起效。
CMD
支持三種格式
CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式;
CMD command param1 param2 在 /bin/bash 中執行,提供給需要交互的應用;
CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數;
指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最后一條會被執行。如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。
ONBUILD:在構建本鏡像時不生效,在基于此鏡像構建鏡像時生效
格式為 ONBUILD [INSTRUCTION]
配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
ENTRYPOINT 和 CMD 的區別:ENTRYPOINT 指定了該鏡像啟動時的入口,CMD 則指定了容器啟動時的命令,當兩者共用時,完整的啟動命令像是 ENTRYPOINT + CMD 這樣。使用 ENTRYPOINT 的好處是在我們啟動鏡像就像是啟動了一個可執行程序,在 CMD 上僅需要指定參數;另外在我們需要自定義 CMD 時不容易出錯。
使用 CMD 的 Dockerfile:
[root@sta2 test]# cat Dockerfile
FROM mysql
CMD ["echo","test"]
使用 ENTRYPOINT 的 Dockerfile:
[root@sta2 entrypoint]# cat Dockerfile
FROM mysql
ENTRYPOINT ["echo","test"]
結論:ENTRYPOINT 不能覆蓋掉執行時的參數,CMD 可以掉覆蓋默認的參數。

可以使用以下命令覆蓋默認的參數,方便調試 Dockerfile 中的 bug:
[root@sta2 entrypoint]# docker run -it --entrypoint=/bin/bash feiyu/entrypoint:1
- 第一章 Docker核心技術(一)
- 第一章 Docker核心技術(二)
- 第一章 Docker核心技術(三)
- 第一章 Docker核心技術(四)
- 第二章 Docker 入門
- 第三章 使用docker鏡像
- 第四章 實戰應用使用Docker構建LNMP環境 (一)
- 第四章 實戰應用使用Docker構建LNMP環境 (二)
- 第四章 實戰應用使用Docker構建LNMP環境 (三)
- 第五章 構建企業級Harbor-Registry
- 第六章 構建Docker應用發布系統(一)
- 第六章 構建Docker應用發布系統(二)
- 第六章 構建Docker應用發布系統(三)
- 第六章 構建Docker應用發布系統(四)