Docker 教程
1、Docker介紹
1.1、什麼是Docker
Docker 是一個開源的應用容器引擎,基於 Go 語言 並遵從Apache2.0協議開源。
Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後發佈到任何流行的 Linux 機器上,也可以實現虛擬化。
容器是完全使用沙箱機制,相互之間不會有任何接口(類似 iPhone 的 app),更重要的是容器性能開銷極低。
1.2、Docker的應用場景
Web 應用的自動化打包和發佈。
自動化測試和持續集成、發佈。
在服務型環境中部署和調整數據庫或其他的後臺應用。
從頭編譯或者擴展現有的OpenShift或Cloud Foundry平臺來搭建自己的PaaS環境。
1.3、Docker 的優點
1、簡化程序:
Docker 讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後發佈到任何流行的 Linux 機器上,便可以實現虛擬化。Docker改變了虛擬化的方式,使開發者可以直接將自己的成果放入Docker中進行管理。方便快捷已經是 Docker的最大優勢,過去需要用數天乃至數週的 任務,在Docker容器的處理下,只需要數秒就能完成。
2、避免選擇恐懼症:
如果你有選擇恐懼症,還是資深患者。Docker 幫你 打包你的糾結!比如 Docker 鏡像;Docker 鏡像中包含了運行環境和配置,所以 Docker 可以簡化部署多種應用實例工作。比如 Web 應用、後臺應用、數據庫應用、大數據應用比如 Hadoop 集羣、消息隊列等等都可以打包成一個鏡像部署。
3、節省開支:
一方面,雲計算時代到來,使開發者不必爲了追求效果而配置高額的硬件,Docker 改變了高性能必然高價格的思維定勢。Docker 與雲的結合,讓雲空間得到更充分的利用。不僅解決了硬件管理的問題,也改變了虛擬化的方式。
1.4、相關連接
2、Docker 架構
Docker 使用客戶端-服務器 (C/S) 架構模式,使用遠程API來管理和創建Docker容器。
Docker 容器通過 Docker 鏡像來創建。
容器與鏡像的關係類似於面向對象編程中的對象與類。
Docker | 面向對象 |
---|---|
容器 | 對象 |
鏡像 | 類 |
名詞 | 解釋 |
---|---|
Docker 鏡像(Images) | Docker 鏡像是用於創建 Docker 容器的模板。 |
Docker 容器(Container) | 容器是獨立運行的一個或一組應用。 |
Docker 客戶端(Client) | Docker 客戶端通過命令行或者其他工具使用 Docker API (https://docs.docker.com/reference/api/docker_remote_api) 與 Docker 的守護進程通信。 |
Docker 主機(Host) | 一個物理或者虛擬的機器用於執行 Docker 守護進程和容器。 |
Docker 倉庫(Registry) | Docker 倉庫用來保存鏡像,可以理解爲代碼控制中的代碼倉庫。Docker Hub(https://hub.docker.com) 提供了龐大的鏡像集合供使用。 |
Docker Machine | Docker Machine是一個簡化Docker安裝的命令行工具,通過一個簡單的命令行即可在相應的平臺上安裝Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
3、Docker使用
3.1、Docker Hello World
Docker 允許你在容器內運行應用程序, 使用 docker run 命令來在容器內運行一個應用程序。
3.1.1、輸出Hello world
#拉取ubuntu:15.10鏡像
docker pull ubuntu:15.10
#在容器ubuntu:15.10中運行 /bin/echo "Hello world"
docker run ubuntu:15.10 /bin/echo "Hello world"
3.1.2、運行交互式的容器
我們通過docker的兩個參數 -i -t,讓docker運行的容器實現"對話"的能力
#交互方式運行ubuntu:15.10
docker run -i -t ubuntu:15.10 /bin/bash
3.1.3、啓動容器(後臺模式)
使用以下命令創建一個以進程方式運行的容器
#後臺方式運行
docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
#查看處於運行狀態的容器
docker ps
#查看容器內輸出
docker logs <CONTAINER ID>
3.1.4、停止容器
我們使用 docker stop 命令來停止容器
#查看運行中的容器
docker ps
#停止指定容器
docker stop <CONTAINER ID>
3.2、Docker 容器使用
3.2.1、Docker 客戶端
docker 客戶端非常簡單 ,我們可以直接輸入 docker 命令來查看到 Docker 客戶端的所有命令選項。
#可以通過以下命令查看docker命令選項
docker
docker --help
docker -h
#使用 docker command --help 更深入的瞭解指定的 Docker 命令使用方法,例如:
docker stats --help
3.2.2、運行一個web應用
前面我們運行的容器並沒有一些什麼特別的用處。
接下來讓我們嘗試使用 docker 構建一個 web 應用程序。
我們將在docker容器中運行一個 Python Flask 應用來運行一個web應用。
docker pull training/webapp # 載入鏡像
docker run -d -P training/webapp python app.py
參數說明:
-d:讓容器在後臺運行。
-P:將容器內部使用的網絡端口映射到我們使用的主機上。
3.2.3、查看 WEB 應用容器
使用 docker ps 來查看我們正在運行的容器:
Docker 開放了 5000 端口(默認 Python Flask 端口)映射到主機端口 32768 上。
這時我們可以通過瀏覽器訪問WEB應用
我們也可以通過 -p 參數來設置不一樣的端口:
docker run -d -p 5000:5000 training/webapp python app.py
docker ps查看正在運行的容器
容器內部的 5000 端口映射到我們本地主機的 5000 端口上。
3.2.4、網絡端口的快捷方式
通過 docker ps 命令可以查看到容器的端口映射,docker 還提供了另一個快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某個確定端口映射到宿主機的端口號。
上面我們創建的 web 應用容器 ID 爲 ee8b2e70bcb3 名字爲 dazzling_babbage。
我可以使用如下命令來查看容器端口的映射情況。
docker port ee8b2e70bcb3
docker port dazzling_babbage
3.2.5、查看 WEB 應用程序日誌
docker logs [ID或者名字] 可以查看容器內部的標準輸出。
3.2.6、查看WEB應用程序容器的進程
我們還可以使用 docker top 來查看容器內部運行的進程
3.2.7、檢查 WEB 應用程序
使用 docker inspect 來查看 Docker 的底層信息。它會返回一個 JSON 文件記錄着 Docker 容器的配置和狀態信息。
3.2.8、停止 WEB 應用容器
3.2.9、重啓WEB應用容器
- 已經停止的容器,我們可以使用命令 docker start 來啓動。
- docker ps -l 查詢最後一次創建的容器:
- 正在運行的容器,我們可以使用 docker restart 命令來重啓
3.2.10、移除WEB應用容器
- 我們可以使用 docker rm 命令來刪除不需要的容器
- 刪除容器時,容器必須是停止狀態,否則會報錯誤
3.3、Docker 鏡像使用
當運行容器時,使用的鏡像如果在本地中不存在,docker 就會自動從 docker 鏡像倉庫中下載,默認是從 Docker Hub 公共鏡像源下載。
下面我們來學習:
1、管理和使用本地 Docker 主機鏡像
2、創建鏡像
3.3.1、列出鏡像列表
我們可以使用 docker images 來列出本地主機上的鏡像。
runoob@runoob:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 90d5884b1ee0 5 days ago 188 MB
php 5.6 f40e9e0f10c8 9 days ago 444.8 MB
nginx latest 6f8d099c3adc 12 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 4 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
training/webapp latest 6fae60ef3446 11 months ago 348.8 MB
選項 | 說明 |
---|---|
REPOSITORY | 表示鏡像的倉庫源 |
TAG | 鏡像的標籤 |
IMAGE ID | 鏡像ID |
CREATED | 鏡像創建時間 |
SIZE | 鏡像大小 |
同一倉庫源可以有多個 TAG,代表這個倉庫源的不同個版本,如ubuntu倉庫源裏,有15.10、14.04等多個不同的版本,我們使用 REPOSITORY:TAG 來定義不同的鏡像。
所以,我們如果要使用版本爲15.10的ubuntu系統鏡像來運行容器時,命令如下:
runoob@runoob:~$ docker run -t -i ubuntu:15.10 /bin/bash
root@d77ccb2e5cca:/#
如果要使用版本爲14.04的ubuntu系統鏡像來運行容器時,命令如下:
runoob@runoob:~$ docker run -t -i ubuntu:14.04 /bin/bash
root@39e968165990:/#
如果你不指定一個鏡像的版本標籤,例如你只使用 ubuntu,docker 將默認使用 ubuntu:latest 鏡像。
3.3.2、獲取一個新的鏡像
當我們在本地主機上使用一個不存在的鏡像時 Docker 就會自動下載這個鏡像。如果我們想預先下載這個鏡像,我們可以使用 docker pull 命令來下載它。
runoob@runoob:~$ docker pull ubuntu:13.10
13.10: Pulling from library/ubuntu
6599cadaf950: Pull complete
23eda618d451: Pull complete
f0be3084efe9: Pull complete
52de432f084b: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:15b79a6654811c8d992ebacdfbd5152fcf3d165e374e264076aa435214a947a3
Status: Downloaded newer image for ubuntu:13.10
下載完成後,我們可以直接使用這個鏡像來運行容器。
3.3.3、查找鏡像
我們可以從 Docker Hub 網站來搜索鏡像,Docker Hub 網址爲: https://hub.docker.com/
我們也可以使用 docker search 命令來搜索鏡像。比如我們需要一個httpd的鏡像來作爲我們的web服務。我們可以通過 docker search 命令搜索 httpd 來尋找適合我們的鏡像。
runoob@runoob:~$ docker search httpd
選項 | 說明 |
---|---|
NAME | 鏡像倉庫源的名稱 |
DESCRIPTION | 鏡像的描述 |
OFFICIAL | 是否docker官方發佈 |
3.3.4、拖取鏡像
我們決定使用上圖中的httpd 官方版本的鏡像,使用命令 docker pull 來下載鏡像。
3.3.5、創建鏡像
當我們從docker鏡像倉庫中下載的鏡像不能滿足我們的需求時,我們可以通過以下兩種方式對鏡像進行更改。
1.從已經創建的容器中更新鏡像,並且提交這個鏡像
2.使用 Dockerfile 指令來創建一個新的鏡像
3.3.6、更新鏡像
更新鏡像之前,我們需要使用鏡像來創建一個容器。
runoob@runoob:~$ docker run -t -i ubuntu:15.10 /bin/bash
root@e218edb10161:/# 在運行的容器內使用 apt-get update 命令進行更新。
在完成操作之後,輸入 exit命令來退出這個容器。
此時ID爲e218edb10161的容器,是按我們的需求更改的容器。我們可以通過命令 docker commit來提交容器副本。
runoob@runoob:~$ docker commit -m="has update" -a="runoob" e218edb10161 runoob/ubuntu:v2
sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8
各個參數說明:
-m:提交的描述信息
-a:指定鏡像作者
e218edb10161:容器ID
runoob/ubuntu:v2:指定要創建的目標鏡像名
我們可以使用 docker images 命令來查看我們的新鏡像 runoob/ubuntu:v2:
runoob@runoob:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
runoob/ubuntu v2 70bf1840fd7c 15 seconds ago 158.5 MB
ubuntu 14.04 90d5884b1ee0 5 days ago 188 MB
php 5.6 f40e9e0f10c8 9 days ago 444.8 MB
nginx latest 6f8d099c3adc 12 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 4 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
training/webapp latest 6fae60ef3446 12 months ago 348.8 MB
使用我們的新鏡像 runoob/ubuntu 來啓動一個容器
runoob@runoob:~$ docker run -t -i runoob/ubuntu:v2 /bin/bash
root@1a9fbdeb5da3:/#
3.3.7、構建鏡像
我們使用命令 docker build , 從零開始來創建一個新的鏡像。爲此,我們需要創建一個 Dockerfile 文件,其中包含一組指令來告訴 Docker 如何構建我們的鏡像。
runoob@runoob:~$ cat Dockerfile
FROM centos:6.7
MAINTAINER Fisher "[email protected]"
RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D
每一個指令都會在鏡像上創建一個新的層,每一個指令的前綴都必須是大寫的。
第一條FROM,指定使用哪個鏡像源
RUN 指令告訴docker 在鏡像內執行命令,安裝了什麼。。。
然後,我們使用 Dockerfile 文件,通過 docker build 命令來構建一個鏡像。
runoob@runoob:~$ docker build -t runoob/centos:6.7 .
Sending build context to Docker daemon 17.92 kB
Step 1 : FROM centos:6.7
---> d95b5ca17cc3
Step 2 : MAINTAINER Fisher "[email protected]"
---> Using cache
---> 0c92299c6f03
Step 3 : RUN /bin/echo 'root:123456' |chpasswd
---> Using cache
---> 0397ce2fbd0a
Step 4 : RUN useradd runoob
......
參數說明:
-t :指定要創建的目標鏡像名
. :Dockerfile 文件所在目錄,可以指定Dockerfile 的絕對路徑
使用docker images 查看創建的鏡像已經在列表中存在,鏡像ID爲860c279d2fec
runoob@runoob:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
runoob/centos 6.7 860c279d2fec About a minute ago 190.6 MB
runoob/ubuntu v2 70bf1840fd7c 17 hours ago 158.5 MB
ubuntu 14.04 90d5884b1ee0 6 days ago 188 MB
php 5.6 f40e9e0f10c8 10 days ago 444.8 MB
nginx latest 6f8d099c3adc 12 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 5 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
centos 6.7 d95b5ca17cc3 6 months ago 190.6 MB
training/webapp latest 6fae60ef3446 12 months ago 348.8 MB
我們可以使用新的鏡像來創建容器
runoob@runoob:~$ docker run -t -i runoob/centos:6.7 /bin/bash
[root@41c28d18b5fb /]# id runoob
uid=500(runoob) gid=500(runoob) groups=500(runoob)
從上面看到新鏡像已經包含我們創建的用戶runoob
3.3.8、設置鏡像標籤
我們可以使用 docker tag 命令,爲鏡像添加一個新的標籤。
runoob@runoob:~$ docker tag 860c279d2fec runoob/centos:dev
docker tag 鏡像ID,這裏是 860c279d2fec ,用戶名稱、鏡像源名(repository name)和新的標籤名(tag)。
使用 docker images 命令可以看到,ID爲860c279d2fec的鏡像多一個標籤。
runoob@runoob:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
runoob/centos 6.7 860c279d2fec 5 hours ago 190.6 MB
runoob/centos dev 860c279d2fec 5 hours ago 190.6 MB
runoob/ubuntu v2 70bf1840fd7c 22 hours ago 158.5 MB
ubuntu 14.04 90d5884b1ee0 6 days ago 188 MB
php 5.6 f40e9e0f10c8 10 days ago 444.8 MB
nginx latest 6f8d099c3adc 13 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 5 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
centos 6.7 d95b5ca17cc3 6 months ago 190.6 MB
training/webapp latest 6fae60ef3446 12 months ago 348.8 MB
3.4、Docker 容器連接
前面我們實現了通過網絡端口來訪問運行在 docker 容器內的服務。下面我們來實現通過端口連接到一個 docker 容器
3.4.1、網絡端口映射
我們創建了一個 python 應用的容器。
runoob@runoob:~$ docker run -d -P training/webapp python app.py
fce072cc88cee71b1cdceb57c2821d054a4a59f67da6b416fceb5593f059fc6d
我們使用 -P 參數創建一個容器,使用 docker ps 來看到端口 5000 綁定主機端口 32768。
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fce072cc88ce training/webapp "python app.py" 4 minutes ago Up 4 minutes 0.0.0.0:32768->5000/tcp grave_hopper
我們也可以使用 -p 標識來指定容器端口綁定到主機端口。
兩種方式的區別是:
-P :是容器內部端口隨機映射到主機的高端口。
-p : 是容器內部端口綁定到指定的主機端口。
runoob@runoob:~$ docker run -d -p 5000:5000 training/webapp python app.py
33e4523d30aaf0258915c368e66e03b49535de0ef20317d3f639d40222ba6bc0
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33e4523d30aa training/webapp "python app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" 8 minutes ago Up 8 minutes 0.0.0.0:32768->5000/tcp grave_hopper
另外,我們可以指定容器綁定的網絡地址,比如綁定 127.0.0.1。
runoob@runoob:~$ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
95c6ceef88ca3e71eaf303c2833fd6701d8d1b2572b5613b5a932dfdfe8a857c
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95c6ceef88ca training/webapp "python app.py" 6 seconds ago Up 6 seconds 5000/tcp, 127.0.0.1:5001->5000/tcp adoring_stonebraker
33e4523d30aa training/webapp "python app.py" 3 minutes ago Up 3 minutes 0.0.0.0:5000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" 10 minutes ago Up 10 minutes 0.0.0.0:32768->5000/tcp grave_hopper
這樣我們就可以通過訪問 127.0.0.1:5001 來訪問容器的 5000 端口。
上面的例子中,默認都是綁定 tcp 端口,如果要綁定 UDP 端口,可以在端口後面加上 /udp。
runoob@runoob:~$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
6779686f06f6204579c1d655dd8b2b31e8e809b245a97b2d3a8e35abe9dcd22a
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6779686f06f6 training/webapp "python app.py" 4 seconds ago Up 2 seconds 5000/tcp, 127.0.0.1:5000->5000/udp drunk_visvesvaraya
95c6ceef88ca training/webapp "python app.py" 2 minutes ago Up 2 minutes 5000/tcp, 127.0.0.1:5001->5000/tcp adoring_stonebraker
33e4523d30aa training/webapp "python app.py" 5 minutes ago Up 5 minutes 0.0.0.0:5000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" 12 minutes ago Up 12 minutes 0.0.0.0:32768->5000/tcp grave_hopper
docker port 命令可以讓我們快捷地查看端口的綁定情況。
runoob@runoob:~$ docker port adoring_stonebraker 5000
127.0.0.1:5001
3.4.2、Docker容器連接
端口映射並不是唯一把 docker 連接到另一個容器的方法。
docker 有一個連接系統允許將多個容器連接在一起,共享連接信息。
docker 連接會創建一個父子關係,其中父容器可以看到子容器的信息。
3.4.3、容器命名
當我們創建一個容器的時候,docker 會自動對它進行命名。另外,我們也可以使用 --name 標識來命名容器,例如:
runoob@runoob:~$ docker run -d -P --name runoob training/webapp python app.py
43780a6eabaaf14e590b6e849235c75f3012995403f97749775e38436db9a441
我們可以使用 docker ps 命令來查看容器名稱。
runoob@runoob:~$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43780a6eabaa training/webapp "python app.py" 3 minutes ago Up 3 minutes 0.0.0.0:32769->5000/tcp runoob