在介紹 Docker 具體的操做前,先簡要複習下 Docker 的架構,這樣能夠更好地幫助咱們理解 Docker 中的各個命令。html
首先咱們一直對 Docker 這個叫法就有些誤解,Docker 其實指代的是用於開發,部署,運行應用的一個平臺。日常中說的 Docker 準確來講是 Docker Engine.python
Docker Engine 是一個 C/S 架構的應用。其中主要的組件有:git
咱們經過給 Docker Client 下發各類指令,而後 Client 經過 Docker daemon 提供的 REST API 接口進行交互,來讓 daemon 處理編譯,運行,部署容器的繁重工做。 大多數狀況下, Docker Client 和 Docker Daemon 運行在同一個系統下,但有時也可使用 Docker Client 來鏈接遠程的 Docker Daemon 進程,也就是遠程的 Server 端。docker
清楚了 Docker 的簡單架構,就能夠了解下具體的命令了。shell
docker build [OPTIONS] PATH | URL | -
Docker 構建鏡像的上下文。數據庫
這裏的上下文指的就是命令的最後一個參數 PATH | URL| -
,具體來講就 docker build .
中的 .
不少人覺得這個 .
是 DockerFile 的位置,其實否則,準確來講是構建上下文的位置。前面說到 Docker 是 C/S 架構,在 Client 端下發具體的命令,在 Server 端(Daemon)執行具體的內容。這也就意味着,構建鏡像的過程實際上是在 Server 端完成的。而上下文的出現,就是爲了把須要的內容傳遞給 Server,這也就爲何在每次構建時都能看到這樣一句話。centos
[root@localhost python_shell]# docker build --rm -t temp/python-test . Sending build context to Docker daemon 4.608kB
這裏的 Sending 其實就是把本地 Client 端的文件內容,拷貝到 Server 端。而許多初學者,在 DockerFile 中寫出了 COPY /opt/xxxx /app
這樣的話,其實就是沒有理解上下文的概念,並不知道在 Server 端是沒有 opt/xxxx
的文件的。緩存
還有的人將 Docker File 放在硬盤根目錄執行,卻不知,這樣會將根目錄全部的文件都拷貝到 Server 端,形成構建極其緩慢。服務器
Options 經常使用參數:網絡
-t
: 打包出鏡像的名稱及標籤,一般寫法爲 name:tag
--rm
: 構建成功後,刪除中間產生的容器。--force-rm=true
: 不管是否構建成功,都刪除中間產生的容器--no-cache
: 構建鏡像時不使用緩存。-f
: 指定 DockerFile 的路徑docker build --no-cache --force-rm -t --no-cache local/centos7:v1 .
經過 FROM
來制定基礎鏡像,命令很簡單,但有一點須要注意的是,必定確切指定基礎鏡像的版本,而不是寫成 latesst
, 由於隨着時間推移,官方的最新鏡像都會一直更新,這樣就會形成沒法構建的狀況。
FROM centos:7 # That's perfect! FROM centos:latest # That's so bad!
RUN 命令用於在容器中執行命令行的命令。通常有兩種寫法:
RUN 後面直接跟 shell 命令就能夠了。切記,在 shell 形式下,不要把命令拆成多行 RUN。由於每一次的 RUN 都會構建一層新的鏡像,保存了不少沒有用的運行信息。並且 Union FS 是由最大層數限制的。因此儘可能將命令合成一行。
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service # That's perfect! RUM yum -y install httpd / # Another perfect solution! yum clean all / systemctl enable httpd.service RUN yum -y install httpd # That's so bad! RUN yum clean all; ....
還有一點須要注意,把構建時沒用的依賴包想着清空。不然的話,隨着鏡像的重複構建,保存了大量的沒有信息。
exec 寫法更像函數調用中的格式。
RUN ["可執行文件", "參數1", "參數2"] RUN ["yum", "-y", "install", "httpd"]
WORKDIR 用於改變各層的工做目錄(也就是進入容器內的默認目錄),若是指定的目錄不存在就會建立它。工做目錄在構建過程當中,能夠被各層都訪問到。
WORKDIR /src
在容器運行時,儘可能對容器的存儲層不進行寫操做,對於像數據庫中這樣動態的數據文件應該用 VOLUME 來保存。而在 DockerFile VOLUME 能夠將目錄指定爲匿名卷。這樣在運行時,若是沒有掛載指定的目錄,並不會像容器的存儲層寫入數據,保證存儲層的無狀態化。
VOLUME /data
官方 Centos7 的鏡像已經包含了 systemd 的功能,只是沒有開啓。這裏只須要以其爲基礎鏡像,打開 systemd 的功能便可。須要注意的是,打開 systemd 須要在運行時開啓特權以掛載 Cgroup 等內容。
編寫 DockerFile
[root@localhost docker_images]# cat Dockerfile FROM centos:7 ENV container docker RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \ systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
打包鏡像
docker build --rm -t local/c7-systemd .
運行鏡像
docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro local/c7-systemd
下面基於上面開啓 systemd 的鏡像爲基礎,打包 Httpd 鏡像。
編寫 DockerFile
FROM local/c7-systemd RUN yum -y install httpd; yum clean all; systemctl enable httpd.service EXPOSE 80
編譯 DockerFile
docker build --rm -t local/c7-systemd-httpd .
運行 Container
docker run --privileged=true -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -p 80:80 local/c7-systemd-httpd
在下載依賴時出現網絡問題,請查看 Docker 代理 這篇文章。
有時咱們須要在容器中運行 python 腳本,下面來打包相似的鏡像。在下載須要的依賴時,一般的服務器並沒訪問公網的能力,這時須要爲容器配置配置代理,在下載依賴後,有時因爲代理的緣由,致使內部的服務器沒法訪問,這時能夠再將設置的代理清空。
建立文件
注意,這裏的文件要和 DockerFile 在同級目錄下。
# 建立 requirements 文件保存依賴 [root@localhost home]# cat python_shell/requirements.txt requests==2.21.0 # 編寫 Python 腳本 [root@localhost home]# cat python_shell/success.py print("python Running", "!");
編寫 DockerFile
FROM python:3.6.8 # set proxy ENV MY_PROXY_URL="http://173.39.112.117:80" ENV HTTP_PROXY=$MY_PROXY_URL \ HTTPS_PROXY=$MY_PROXY_URL \ FTP_PROXY=$MY_PROXY_URL \ http_proxy=$MY_PROXY_URL \ https_proxy=$MY_PROXY_URL \ ftp_proxy=$MY_PROXY_URL WORKDIR /src COPY . . RUN ["pip", "install", "--no-cache-dir", "-r", "./requirements.txt"] # clear the proxy ENV MY_PROXY_URL= ENV HTTP_PROXY=$MY_PROXY_URL \ HTTPS_PROXY=$MY_PROXY_URL \ FTP_PROXY=$MY_PROXY_URL \ http_proxy=$MY_PROXY_URL \ https_proxy=$MY_PROXY_URL \ ftp_proxy=$MY_PROXY_URL CMD ["python", "./success.py"]
打包鏡像
docker build --rm -t temp/python-test .
運行鏡像
[root@localhost home]# docker run temp/python-test python Running !
https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/