Docker
是個劃時代的開源項目,它完全釋放了計算虛擬化的威力,極大提升了應用的運行效率,下降了雲計算資源供應的成本!使用 Docker
,可讓應用的部署、測試和分發都變得史無前例的高效和輕鬆!php
不管是應用開發者、運維人員、仍是其餘信息技術從業人員,都有必要認識和掌握 Docker
,節約有限的時間。html
要安裝Docker CE
,您須要這些Ubuntu
版本的64位版本:node
Ubuntu x86_64,Linux armhf,s390x(IBM Z)和ppc64le(IBM Power)架構上支持Docker CE
。python
老版本的Docker
被稱爲docker
或docker-engine
。若是安裝了這些,請將其卸載:mysql
$ apt-get remove docker docker-engine docker.io
首次在新的主機上安裝Docker CE
以前,須要設置Docker
存儲庫。以後,您能夠從存儲庫安裝和更新Docker
。linux
1.更新apt
軟件包索引:nginx
$ apt-get update
2.安裝軟件包以容許apt
經過HTTPS
使用存儲庫:git
$ apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
3.添加Docker
的官方GPG
密鑰:github
鑑於國內網絡問題,強烈建議使用國內源,官方源請在註釋中查看。golang
$ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # 官方源 # $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4.添加 Docker 軟件源
鑑於國內網絡問題,強烈建議使用國內源,官方源請在註釋中查看。
而後,咱們須要向 source.list
中添加 Docker
軟件源
$ sudo add-apt-repository \ "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \ $(lsb_release -cs) \ stable" # 官方源 # $ sudo add-apt-repository \ # "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ # $(lsb_release -cs) \ # stable"
以上命令會添加穩定版本的 Docker CE APT
鏡像源,若是須要最新或者測試版本的 Docker CE
請將 stable
改成 edge
或者 test
。從 Docker 17.06
開始,edge test
版本的 APT
鏡像源也會包含穩定版本的 Docker
。
1.更新apt軟件包索引。
$ apt-get update
2.安裝最新版本的Docker CE,或者轉到下一步安裝特定版本。任何現有的Docker安裝都將被替換。
$ apt-get install docker-ce
3.在生產系統上,您應該安裝特定版本的Docker CE,而不是始終使用最新版本。此輸出被截斷。列出可用的版本。
$ apt-cache madison docker-ce docker-ce | 17.12.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.09.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.09.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.2~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages docker-ce | 17.06.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu zesty/stable amd64 Packages
列表的內容取決於啓用了哪一個存儲庫。選擇一個特定的版本進行安裝。第二列是版本字符串。第三列是存儲庫名稱,它指出了軟件包來自哪一個存儲庫,並經過擴展其穩定性級別。要安裝特定版本,請將版本字符串附加到包名稱,並用等號(=)將它們分開:
$ sudo apt-get install docker-ce=<VERSION>
4.經過運行hello-world
映像驗證是否正確安裝了Docker CE
。
$ docker run hello-world
這個命令下載一個測試圖像並在容器中運行。容器運行時,會打印一條信息消息並退出。
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world ca4f61b1923c: Pull complete Digest: sha256:445b2fe9afea8b4aa0b2f27fe49dd6ad130dfe7a8fd0832be5de99625dad47cd Status: Downloaded newer image for hello-world:latest 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. (amd64) 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 Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/
默認狀況下,docker
命令會使用 Unix socket
與 Docker
引擎通信。而只有 root
用戶和 docker
組的用戶才能夠訪問 Docker
引擎的 Unix socket
。出於安全考慮,通常 Linux
系統上不會直接使用 root
用戶。所以,更好地作法是將須要使用 docker
的用戶加入 docker
用戶組。
要建立docker
組並添加您的用戶:
1.建立docker組。
$ sudo groupadd docker
2.將您的用戶添加到docker組中。
$ sudo usermod -aG docker $USER
3.註銷並從新登陸,若是在虛擬機上進行測試,則可能須要從新啓動虛擬機才能使更改生效。
4.驗證您能夠不運行docker
命令sudo
。
$ docker run hello-world
1.卸載Docker CE
軟件包:
$ sudo apt-get purge docker-ce
2.主機上的圖像,容器,卷或自定義配置文件不會自動刪除。刪除全部圖像,容器和卷:
$ sudo rm -rf /var/lib/docker
這條命令會用nginx
鏡像啓動一個容器,命名爲 myweb
,而且映射了 80
端口,這樣咱們能夠用瀏覽器去訪問這個 nginx
服務器。
$ docker run --name myweb -d -p 80:80 nginx
直接訪問:http://localhost;若是使用的是 Docker Toolbox,或者是在虛擬機、雲服務器上安裝的 Docker,則須要將 localhost 換爲虛擬機地址或者實際雲服務器地址。
如今,假設咱們很是不喜歡這個歡迎頁面,咱們但願改爲歡迎 Docker
的文字,咱們可使用 docker exec
命令進入容器,修改其內容。
$ docker exec -it myweb bash root@5ceb0c8274ca:/# echo '<h1>Welcome to Docker!</h1>' > /usr/share/nginx/html/index.html root@5ceb0c8274ca:/# exit exit
直接訪問:http://localhost;
咱們修改了容器的文件,也就是改動了容器的存儲層。咱們能夠經過 docker diff
命令看到具體的改動。COMMENT
列有備註!
$ docker diff myweb C /root A /root/.bash_history C /run A /run/nginx.pid C /usr/share/nginx/html/index.html C /var/cache/nginx D /var/cache/nginx/client_temp D /var/cache/nginx/fastcgi_temp D /var/cache/nginx/proxy_temp D /var/cache/nginx/scgi_temp D /var/cache/nginx/uwsgi_temp root@souyunku:~/mydocker#
咱們能夠用下面的命令將容器保存爲鏡像:
$ docker commit \ --author "penglei <admin@souyunku.com>" \ --message "修改了默認網頁" \ myweb \ nginx:v2 sha256:33b2e2aefccbaba54021c85ef7966c7d488abaa0677728e1b057c56a7734a4f0
其中 --author
是指定修改的做者,而 --message
則是記錄本次修改的內容。這點和 git
版本控制類似,不過這裏這些信息能夠省略留空。
咱們能夠在 docker image ls
中看到這個新定製的鏡像:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx v2 33b2e2aefccb About a minute ago 108MB nginx latest 3f8a4339aadd 3 days ago 108MB hello-world latest f2a91732366c 5 weeks ago 1.85kB
$ docker history nginx:v2 IMAGE CREATED CREATED BY SIZE COMMENT 33b2e2aefccb 2 minutes ago nginx -g daemon off; 325B 修改了默認網頁 3f8a4339aadd 3 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B <missing> 3 days ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B <missing> 3 days ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B <missing> 3 days ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B <missing> 3 days ago /bin/sh -c set -x && apt-get update && apt… 53.2MB <missing> 3 days ago /bin/sh -c #(nop) ENV NJS_VERSION=1.13.8.0.… 0B <missing> 3 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.13.8-… 0B <missing> 2 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B <missing> 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 2 weeks ago /bin/sh -c #(nop) ADD file:f30a8b5b7cdc9ba33… 55.3MB
新的鏡像定製好後,咱們能夠來運行這個鏡像。
$ docker run --name web2 -d -p 81:80 nginx:v2 ed8c54aeb3c540981b892c0cdfbf9330114ecc935149190e073f49295f2ae147
直接訪問:http://localhost:81;若是使用的是 Docker Toolbox,或者是在虛擬機、雲服務器上安裝的 Docker,則須要將 localhost 換爲虛擬機地址或者實際雲服務器地址。
從剛纔的 docker commit
的學習中,咱們能夠了解到,鏡像的定製實際上就是定製每一層所添加的配置、文件。若是咱們能夠把每一層修改、安裝、構建、操做的命令都寫入一個腳本,用這個腳原本構建、定製鏡像,那麼以前說起的沒法重複的問題、鏡像構建透明性的問題、體積的問題就都會解決。這個腳本就是 Dockerfile
。
Dockerfile
是一個文本文件,其內包含了一條條的指令(Instruction
),每一條指令構建一層,所以每一條指令的內容,就是描述該層應當如何構建。
還以以前定製 nginx
鏡像爲例,此次咱們使用 Dockerfile
來定製。
在一個空白目錄中,創建一個文本文件,並命名爲 Dockerfile
:
$ mkdir mynginx $ cd mynginx $ touch Dockerfile
其內容爲:
FROM nginx RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
這個 Dockerfile
很簡單,一共就兩行。涉及到了兩條指令,FROM
和 RUN
。
所謂定製鏡像,那必定是以一個鏡像爲基礎,在其上進行定製。就像咱們以前運行了一個 nginx
鏡像的容器,再進行修改同樣,基礎鏡像是必須指定的。而 FROM 就是指定基礎鏡像,所以一個 Dockerfile
中 FROM
是必備的指令,而且必須是第一條指令。
在 Docker Store
上有很是多的高質量的官方鏡像,有能夠直接拿來使用的服務類的鏡像,如 nginx
、redis
、mongo
、mysql
、httpd
、php
、tomcat
等;也有一些方便開發、構建、運行各類語言應用的鏡像,如 node
、openjdk
、python
、ruby
、golang
等。能夠在其中尋找一個最符合咱們最終目標的鏡像爲基礎鏡像進行定製。
若是沒有找到對應服務的鏡像,官方鏡像中還提供了一些更爲基礎的操做系統鏡像,如 ubuntu
、debian
、centos
、fedora
、alpine
等,這些操做系統的軟件庫爲咱們提供了更廣闊的擴展空間。
除了選擇現有鏡像爲基礎鏡像外,Docker
還存在一個特殊的鏡像,名爲 scratch
。這個鏡像是虛擬的概念,並不實際存在,它表示一個空白的鏡像。
FROM scratch ...
若是你以 scratch
爲基礎鏡像的話,意味着你不以任何鏡像爲基礎,接下來所寫的指令將做爲鏡像第一層開始存在。
不以任何系統爲基礎,直接將可執行文件複製進鏡像的作法並不罕見,好比 swarm
、coreos/etcd
。對於 Linux
下靜態編譯的程序來講,並不須要有操做系統提供運行時支持,所需的一切庫都已經在可執行文件裏了,所以直接 FROM
scratch
會讓鏡像體積更加小巧。使用 Go
語言 開發的應用不少會使用這種方式來製做鏡像,這也是爲何有人認爲 Go 是特別適合容器微服務架構的語言的緣由之一。
RUN
指令是用來執行命令行命令的。因爲命令行的強大能力,RUN
指令在定製鏡像時是最經常使用的指令之一。其格式有兩種:
shell
格式:RUN
<命令>,就像直接在命令行中輸入的命令同樣。剛纔寫的 Dockerfile
中的 RUN
指令就是這種格式。RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
既然 RUN
就像 Shell
腳本同樣能夠執行命令,那麼咱們是否就能夠像 Shell
腳本同樣把每一個命令對應一個 RUN
呢?好比這樣:
FROM debian:jessie RUN apt-get update RUN apt-get install -y gcc libc6-dev make RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install
以前說過,Dockerfile
中每個指令都會創建一層,RUN
也不例外。每個 RUN
的行爲,就和剛纔咱們手工創建鏡像的過程同樣:新創建一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。
而上面的這種寫法,建立了 7 層鏡像。這是徹底沒有意義的,並且不少運行時不須要的東西,都被裝進了鏡像裏,好比編譯環境、更新的軟件包等等。結果就是產生很是臃腫、很是多層的鏡像,不只僅增長了構建部署的時間,也很容易出錯。 這是不少初學 Docker 的人常犯的一個錯誤。
Union FS
是有最大層數限制的,好比 AUFS
,曾經是最大不得超過 42 層,如今是不得超過 127 層。
上面的 Dockerfile
正確的寫法應該是這樣:
FROM debian:jessie RUN buildDeps='gcc libc6-dev make' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps
首先,以前全部的命令只有一個目的,就是編譯、安裝 redis
可執行文件。所以沒有必要創建不少層,這只是一層的事情。所以,這裏沒有使用不少個 RUN
對一一對應不一樣的命令,而是僅僅使用一個 RUN
指令,並使用 && 將各個所需命令串聯起來。將以前的 7 層,簡化爲了 1 層。在撰寫 Dockerfile
的時候,要常常提醒本身,這並非在寫 Shell
腳本,而是在定義每一層該如何構建。
而且,這裏爲了格式化還進行了換行。Dockerfile
支持 Shell
類的行尾添加 的命令換行方式,以及行首 # 進行註釋的格式。良好的格式,好比換行、縮進、註釋等,會讓維護、排障更爲容易,這是一個比較好的習慣。
此外,還能夠看到這一組命令的最後添加了清理工做的命令,刪除了爲了編譯構建所須要的軟件,清理了全部下載、展開的文件,而且還清理了 apt
緩存文件。這是很重要的一步,咱們以前說過,鏡像是多層存儲,每一層的東西並不會在下一層被刪除,會一直跟隨着鏡像。所以鏡像構建時,必定要確保每一層只添加真正須要添加的東西,任何無關的東西都應該清理掉。
不少人初學 Docker
製做出了很臃腫的鏡像的緣由之一,就是忘記了每一層構建的最後必定要清理掉無關文件。
好了,讓咱們再回到以前定製的 nginx
鏡像的 Dockerfile
來。如今咱們明白了這個 Dockerfile
的內容,那麼讓咱們來構建這個鏡像吧。
在 Dockerfile
文件所在目錄執行:
$ docker build -t nginx:v3 . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM nginx ---> 3f8a4339aadd Step 2/2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html ---> Running in 5cdac6d29a52 Removing intermediate container 5cdac6d29a52 ---> 56a1b67b2533 Successfully built 56a1b67b2533 Successfully tagged nginx:v3
從命令的輸出結果中,咱們能夠清晰的看到鏡像的構建過程。在 Step 2
中,如同咱們以前所說的那樣,RUN
指令啓動了一個容器 5cdac6d29a52
,執行了所要求的命令,並最後提交了這一層 56a1b67b2533
,隨後刪除了所用到的這個容器 5cdac6d29a52
這裏咱們使用了 docker build
命令進行鏡像構建。其格式爲:
$ docker build [選項] <上下文路徑/URL/->
鏡像構建上下文(Context)若是注意,會看到 docker build
命令最後有一個 .
。.
表示當前目錄
Git repo
進行構建或許你已經注意到了,docker build
還支持從 URL
構建,好比能夠直接從 Git repo
中構建:
感謝:漠然提供 Git dockerfile repo
$ docker build https://github.com/mritd/dockerfile.git#:alpine-glibc
... Executing ca-certificates-20171114-r0.post-deinstall Executing busybox-1.27.2-r6.trigger OK: 11 MiB in 14 packages Removing intermediate container baf41e622959 ---> aded3329be1b Step 3/3 : ENV LANG=C.UTF-8 ---> Running in 8c34e0f4d25b Removing intermediate container 8c34e0f4d25b ---> c493a5aa5eb7 Successfully built c493a5aa5eb7
這行命令指定了構建所需的 Git repo
,而且指定默認的 master
分支,構建目錄爲 /alpine-glibc/,而後 Docker
就會本身去 git clone
這個項目、切換到指定分支、並進入到指定目錄後開始構建。
$ docker build http://server/context.tar.gz
若是所給出的 URL 不是個 Git repo
,而是個 tar 壓縮包,那麼 Docker 引擎會下載這個包,並自動解壓縮,以其做爲上下文,開始構建。
Dockerfile
進行構建$ docker build - < Dockerfile
或
$ cat Dockerfile | docker build -
若是標準輸入傳入的是文本文件,則將其視爲 Dockerfile
,並開始構建。這種形式因爲直接從標準輸入中讀取 Dockerfile
的內容,它沒有上下文,所以不能夠像其餘方法那樣能夠將本地文件 COPY 進鏡像之類的事情。
$ docker build - < context.tar.gz
若是發現標準輸入的文件格式是 gzip、bzip2
以及 xz
的話,將會使其爲上下文壓縮包,直接將其展開,將裏面視爲上下文,並開始構建。
參考:Docker — 從入門到實踐
https://www.gitbook.com/download/pdf/book/yeasy/docker_practice
參考:Docker 官網 Get Docker CE for Ubuntu