Last active
August 29, 2015 14:10
-
-
Save ymhuang0808/c829ade6896ecba557fc to your computer and use it in GitHub Desktop.
Docker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Docker 入門 | |
===================== | |
**Docker** 是一個開源專案,支援多平台,從筆電到公、私有雲上能進行快速部署輕量、獨立的作業環境。**Docker** 使用 Linux 核心中的功能,像 Namespace 及 Control Groups (cgroups) 等,來達到建置獨立的環境及控制 CPU 、Memory 、網路等資源。 | |
![Docker logo](https://lh5.googleusercontent.com/-i5itJJ2tfaY/VGmdrNgDHQI/AAAAAAAADj0/QTalLMbSc08/s500/small_v.png "small_v.png") | |
> **專案網址:** http://www.docker.com/ | |
### Docker 與虛擬化的不同 | |
**Docker** 提供應用程式在獨立的 container 中執行,這些 container 並不需要額外依附在 [hypervisor](http://en.wikipedia.org/wiki/Hypervisor) 或 guest OS 上。 | |
##### 虛擬化 | |
![Virtualization diagram](https://lh6.googleusercontent.com/-xDnBtlJadUs/VGmvyMUIPxI/AAAAAAAADkM/fkH0nQ1QViY/s400/Virtualization_architecture.png "Virtualization_architecture.png") | |
##### Docker Container | |
![Docker container daigram](https://lh4.googleusercontent.com/-Q80Fsg-GuBI/VGmwTMcC8VI/AAAAAAAADk0/Bzi1_807I88/s400/Container_architecture.png "Container_architecture.png") | |
---------- | |
安裝 | |
--------- | |
### Ubuntu | |
`$ sudo apt-get update` | |
`$ sudo apt-get install docker.io` | |
### Mac OS X, Windows | |
需要安裝 **Boot2Docker** ,因為 **Docker Engine** 有用到 Linux 的特定功能,所以 **Boot2Docker** 會用 Virtualbox 建立 Linux VM ,在 Linux VM 上開啟 **Docker** daemon 由在 Mac OS X 或 Windows 的 **Docker** client 去操作Linux VM 上 **Docker** daemon *(後面會在詳述)*。 | |
> **Boot2Docker 安裝參考:** | |
> | |
> Mac OS X : https://docs.docker.com/installation/mac/ | |
> Windows : https://docs.docker.com/installation/windows/ | |
備註:在 Mac OS X 執行 `docker` 指令不用加上 `sudo` | |
---------- | |
操作 Docker | |
--------- | |
對 **Docker** 進行操作,使用 **Docker** client 藉由 UNIX sockets 或網路 (RESTful API) 對主機上的 **Docker** daemon 進行控制,當然**Docker** client 與 **Docker** daemon 可以是同一台或不同主機上 。 | |
![Docker client & Docker daemon](https://lh3.googleusercontent.com/-_OgiPDpXl8s/VGnJLnkbBjI/AAAAAAAADlM/XeID2bu6mUQ/s500/docker-server-client.png "docker-server-client.png") | |
> **參考 Docker Remote API :** | |
> | |
> Docker Remote API - Docker Documentation | |
> https://docs.docker.com/reference/api/docker_remote_api/ | |
### Docker 重要元件 | |
介紹如何從 **Docker** client 下指令前,先介紹 **Docker ** 中的三個主要部分: | |
- **Docker** Images | |
從 Images 開啟 **Docker** container ,images 是唯讀的,也就是直接 結束 container 後,在 **Docker** container 變更的資料並不會儲存在 image 內,但是 **Docker** 能對變更後的 container 建立或更新 image。 | |
- **Docker** Containers | |
**Docker** containers 提供獨立、安全的環境給應用程式執行,而 **Docker** container 是從 **Docker** image 建立。 | |
- **Docker** Registries | |
將 **Docker** images 上傳、下載到公開或私有的 **Docker** registries 上,與其他人分享,公開的 **Docker** registries 像 **Docker Hub** 提供了許多不同的 images ,如:Ubuntu 或 Ubuntu 環境下安裝 Ruby on Rails 的 images ,只要下載來,就能直接開啟成 **Docker** container。 | |
---------- | |
### 註冊及登入 Docker Hub 帳號 | |
在前面有提到 **Docker Hub** 上提供了許多 images 可以使用,要先註冊在 **Docker Hub** 上的帳號,註冊網址:https://hub.docker.com/account/signup/ | |
接著可以利用指令來登入 **Docker Hub** ,並且用指令來下載、上傳 Docker images: | |
`$ sudo docker login` | |
> Username: [ENTER YOUR USERNAME] | |
> Password: | |
> Email: [ENTER YOUR EMAIL] | |
> Login Succeeded | |
---------- | |
### 操作 Docker Container | |
#### 建立一個新的 container | |
先來暖身一下,啟動一個 CentOS 6 container,希望能執行指令來顯示今天的日期與時間。 | |
使用 `sudo docker run` 開啟一個新的 container: | |
`$ sudo docker run centos:centos6 /bin/date` | |
> Unable to find image 'centos:centos6' locally | |
> centos:centos6: The image you are pulling has been verified | |
> 511136ea3c5a: Pull complete | |
> 5b12ef8fd570: Pull complete | |
> Status: Downloaded newer image for centos:centos6 | |
> Mon Dec 1 03:25:41 GMT 2014 | |
- `docker run` 啟動一個新的 container | |
- `centos:centos6` CentOS 6.X (目前 CentOS 6 最新版為 6.6),第一個 `centos` 是 repo 名稱, `centos6` 是 repo 內 tags ,到 [Docker Hub 網站](https://hub.docker.com/)搜尋 *centos* 後,在 *centos* repo 頁面上就會呈現有哪些 tags 。 | |
![enter image description here](https://lh5.googleusercontent.com/-AGkSeGCOJnA/VHv3EeewoxI/AAAAAAAADoA/vOzwnyFhsrc/s500/centos_Repository___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png "centos_Repository___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png") | |
- `/bin/date` 開啟 container 後執行的指令 | |
輸出結果的第 1 行到第 5 行是,因為 docker 主機上原來並沒有 centos6 的 image 檔案,所以會先從 Docker Hub 下載,輸出結果的最後一行就是執行的 `date` 指令。另外可以發現,如果扣除下載 image 時間,開啟一個 container 只要非常短的時間。 | |
`docker run` 還有其他參數可以進入 container 的終端機指令互動模式下: | |
`$ sudo docker run -t -i centos:centos6 bash | |
[root@ea27583b1dba /]# whoami | |
root` | |
- -t 開啟 tty 進入 container | |
- -i 透過 STDIN 與 container 進行互動 | |
如果要離開 container 輸入 `exit` 或按 `control/Ctrl` + `D`,目前使用的這個 container 就會結束,而下次在開啟的 container 又是一個全新的。 | |
不想結束 container 的話,可以先按 `control/Ctrl` + `P`,再按 `control/Ctrl` + `Q` ,就可以跳離開這個 container 的 tty。 | |
---------- | |
#### 管理 Container | |
如果只是離開了 container 終端機, container 並沒有關閉或停止執行,所以接下來要介紹如何來管理 container。 | |
##### Container ID | |
每一個 container 都有一個唯一的 *CONTAINER ID*,在上面的部分,執行 `sudo docker run -t -i centos:centos6 bash` 開啟新的 container 後,會進入 container 的終端機內: | |
`[root@ea27583b1dba /]# whoami | |
root` | |
`ea27583b1dba` 就是 *CONTAINER ID*,都是利用此 id 來分別不同的 container。 | |
##### 列出 Container | |
Docker client 提供了 `docker ps` 可以查看目前開啟了哪些 container 且正在執行中: | |
`$ sudo docker ps` | |
`CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES` | |
`053efe3aaf7b centos:centos6 "/bin/bash" 3 seconds ago Up 2 seconds tender_mclean` | |
##### 在 Container 中執行指令 | |
離開了 container 的終端機後,並沒有將 container 關掉,可以用 `docker exec` 在 container 中執行指令,例如下面範例就是再回到`053efe3aaf7b` container 的終端機: | |
`$ sudo docker exec -t -i CONTAINER_ID bash | |
[root@053efe3aaf7b /]#` | |
##### 停止 Container | |
想要讓在執行中的 container 停止,用 `docker stop` 停止執行中的 container : | |
`$ sudo docker stop CONTAINER_ID` | |
`$ sudo docker ps -a` | |
`CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES` | |
`053efe3aaf7b centos:centos6 "/bin/bash" 3 seconds ago Exited (-1) About a minute ago tender_mclean` | |
備註: `docker ps` `-a` 參數,可以看到所有沒被刪除的 container。 | |
##### 開啟停止的 Container | |
開啟停止的 container `docker start`: | |
`$ sudo docker start CONTAINER_ID` | |
開啟後會執行一開始建立這個 container 的指令及參數,所以如果建立的時候,並沒有開啟終端機與互動模式,執行完指令後,container 又結束了。 | |
##### 刪除 Container | |
透過 `docker ps -a` 可以列出所有建立過且沒被刪除的 container: | |
`$ sudo docker ps -a` | |
`CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES | |
395e303d085b centos:centos6 "/bin/bash" About an hour ago Exited (-1) 32 minutes ago tender_hypatia | |
e516847c6563 centos:centos6 "/bin/bash" About an hour ago Exited (127) About an hour ago hopeful_mcclintock | |
f4181083713c centos:centos6 "/bin/bash" About an hour ago Exited (130) About an hour ago desperate_fermat` | |
`docker rm` 刪除不需要的 container : | |
`$ sudo docker rm CONTAINER_ID` | |
##### Container 內建立額外的掛載點 | |
在 container 建立時,可以再建自訂的掛載點: | |
`$ docker run -t -i -v /myData centos:centos6 bash` | |
`[root@20d24e944789 /]# df -h | |
Filesystem Size Used Avail Use% Mounted on | |
rootfs 19G 459M 17G 3% / | |
... | |
/dev/sda1 19G 459M 17G 3% /myData | |
...` | |
- -v 在 container 內的掛載點 | |
##### 共享主機與 Container 資料 | |
Docker 也提供了可以與主機目錄共享的資料的功能,這在開發的時候蠻好用的,只要把專案目錄掛載到 container 內,就能直接在 container 測試、執行。 | |
我們將主機上的 */home/aming/Docker/tutorial/* 目錄掛到 container 內的 */app* 目錄: | |
`$ sudo docker run -t -i -v /home/aming/Docker/tutorial/:/app tutum/apache-php bash` | |
- -v *[HOST_DIR]:[CONTAINER_DIR]* 將 host OS 上的目錄掛載到 container 內的掛載點 | |
![共享主機與 Container 資料](https://lh3.googleusercontent.com/RalT6jamd2_Ea9Vj0ATgLR_ECxwkfkVOSeAK4Gw6NTQ=s400 "host_os_container_volume.png") | |
##### 移除不需要的 Container | |
`$ sudo docker rm c28d95ed172f` | |
`c28d95ed172f` | |
- *c28d95ed172f* 為 container ID | |
---------- | |
### 管理 Docker Image | |
前面有提到,使用 `docker run` 建立新的 container 時,如果 Docker 發現沒有符合的 image 預設會去 Docker Hub 下載,那我們該如何知道目前有哪些可用的 images ? | |
`docker images` 可以列出主機內已經存在的 image: | |
`sudo docker images` | |
`$ docker images | |
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE` | |
`centos centos6 70441cac1ed5 3 weeks ago 215.8 M` | |
可以看到前面所提到的 image 的「repo 名稱」、「tag 名稱」等資訊。 | |
#### 搜尋 Images | |
搜尋 *php* 關鍵字: | |
`$ sudo docker search php` | |
`NAME DESCRIPTION STARS OFFICIAL AUTOMATED | |
php While designed for web development, the PH... 56 [OK] | |
tutum/apache-php Apache+PHP base image - listens in port 80... 40 [OK]` | |
#### 下載 Image | |
我們下載搜尋到的 *tutum/apache-php* : | |
`$ sudo docker pull tutum/apache-php` | |
`Pulling repository tutum/apache-php | |
...` | |
再看一下是不是有這一個 image 了: | |
`$ sudo docker images` | |
`REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE` | |
`tutum/apache-php latest 7e6d00854917 9 days ago 255.3 MB` | |
#### 製作新的 Image | |
把剛才下載下來的 tutum/apache-php 已經有 Apache 及 PHP 環境,再利用,安裝 PHPUnit,製作成新的 image: | |
開啟一個新的 Container: | |
`$ sudo docker run -t -i tutum/apache-php bash` | |
Container 內 PHPUnit 安裝(示範用): | |
`root@aeeb1980c96e:/app# apt-get install wget` | |
`root@aeeb1980c96e:/app# cd /usr/local/bin ; | |
\ wget https://phar.phpunit.de/phpunit.phar` | |
`root@aeeb1980c96e:/app# chmod +x phpunit.phar` | |
`root@aeeb1980c96e:/app# exit` | |
使用 `docker commit` 製作新的 image: | |
`$ sudo docker commit -m="Add PHPUnit and xdebug" \ | |
-a="Huang Yi-Ming" \ | |
aeeb1980c96e ymhuang0808/phpunit-testing:php5.5.9` | |
`$ sudo docker images` | |
`REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE | |
ymhuang0808/phpunit-testing php5.5.9 be964598c221 13 hours ago 290.6 MB` | |
我們建立一個新的 container,container ID 為 *aeeb1980c96e* ,在 container 內建立好需要的環境後,把修改的 container 建立成一個新 image 檔案。 | |
- `-m` 製作這個 image 的訊息 | |
- `-a` 這一個 image 的作者 | |
- *aeeb1980c96e* 則為上面有提到的 container ID | |
- *ymhuang0808/phpunit-testing* repo 名稱,通常斜線( / )前面為在 Docker Hub 的帳號名稱,後面則是 repo 名稱 | |
- *php5.5.9* tag 名稱,因為 repo 內可能會有不版本的 image ,就可以利用 tag 來區分 | |
#### 上傳至 Docker Hub | |
我們做了一個新的 image 後,可以上傳到 Docker Hub 或私有的 regitry 將 image 分享出去。 | |
首先,我們需要到 Docker Hub 網站建立一個自己的 repo: | |
1. 點選「Add Repository」,選擇「Respository」 | |
![點選新增 repo](https://lh6.googleusercontent.com/-ZwDDhba6Yow/VH1XklbuSVI/AAAAAAAADpI/KxlUztac6Jc/s400/View_Public_Profile___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png "View_Public_Profile___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png") | |
2. 填寫 Repo 名稱(注意要小寫)與描述,接著點選「Add Repository」 | |
![填寫 repo 資訊](https://lh3.googleusercontent.com/-mZIoi2L7M50/VH1XacQoeqI/AAAAAAAADo0/lNbuNG2iOLg/s400/Add_Repository___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png "Add_Repository___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png") | |
3. 成功在 Docker Hub 上建立 repo | |
![Repo 頁面](https://lh6.googleusercontent.com/8ts3gyZr--9QWYx1iCn8KawUumRAlikpq91vAAA10Qo=s400 "ymhuang0808_phpunit-testing_Repository___Docker_Hub_Registry_-_Repositories_of_Docker_Images.png") | |
在 Docker Hub 建立好 repo 後,就可以將 image 使用 `docker push` 上傳至 Docker Hub: | |
`$ sudo docker push ymhuang0808/phpunit-testing` | |
`The push refers to a repository [ymhuang0808/phpunit-testing] (len: 1) | |
Sending image list | |
Pushing repository ymhuang0808/phpunit-testing (1 tags) | |
511136ea3c5a: Image already pushed, skipping | |
... | |
Pushing tag for rev [be964598c221] on {https://cdn-registry-1.docker.io/v1/repositories/ymhuang0808/phpunit-testing/tags/php5.5.9}` | |
#### 移除 Image | |
`$ sudo docker rmi ymhuang0808/phpunit-testing:php5.5.9` | |
如果無法刪除可能是有 container 使用了這個 image ,所以要先用 `docker rm` 移除使用的 container,才能順利移除 image。 | |
---------- | |
### 撰寫 Dockerfile | |
在上面了解到能自己製作 image ,並且透過 Docker 分享出去,除了可以利用做好的 image 方便建立一個新的 container 外,也可以用 Dockerfile 寫好建立 image 的腳本檔案,再用 `docker build` 就能幫我們建立一個 image,然後一樣可以上傳到 Docker Hub 分享出去! | |
下面要示範如何使用 Dockerfile 來自動建立 image。跟上面一樣,我們利用 *tutum/apache-php* 來建 PHPUnit 的環境。 | |
#### 建立目錄與 Dockerfile | |
`$ mkdir ~/dockerfile-demo && cd ~/dockerfile-demo` | |
`$ touch Dockerfile` | |
#### 編輯 Dockerfile | |
`$ vi Dockerfile` | |
加入以下內容: | |
`FROM tutum/apache-php:latest | |
MAINTAINER Huang AMing <[email protected]> | |
RUN sed -i 's/archive.ubuntu.com/free.nchc.org.tw/g' \ | |
/etc/apt/sources.list | |
RUN apt-get update \ | |
&& apt-get install -y php5-xdebug | |
ADD https://phar.phpunit.de/phpunit.phar /usr/local/bin/ | |
RUN cd /usr/local/bin \ | |
&& chmod +x phpunit.phar \ | |
&& mv phpunit.phar phpunit` | |
- `FROM ` 以什麼 image 為基底 | |
- `MAINTAINER` 維護 image 的人 | |
- `RUN` 在 image 內執行的指令 | |
- `ADD` 將本機的檔案或遠端的檔案加入到 image 內的目錄,如果是壓縮檔會自動解壓縮。想將本機檔案或目錄複製到 image 可以使用 `COPY` | |
#### 透過 Dockerfile 建立 Image | |
Dockerfile 就像一個腳本檔案,用 `docker build` 會根據 Dockerfile 內容來建立新的 image: | |
`$ sudo docker build -t="ymhuang0808/phpunit-testing:php5.5.9" .` | |
`Sending build context to Docker daemon 2.56 kB | |
Sending build context to Docker daemon | |
Step 0 : FROM tutum/apache-php:latest | |
---> 7e6d00854917 | |
Step 1 : MAINTAINER Huang AMing <[email protected]> | |
---> Running in 22412a8891e1 | |
... | |
Successfully built 5f466619af2d` | |
- -t repo 名稱加上 tag ,以冒號( : )區隔 | |
- . 依據當下目錄下的`Dockerfile` | |
參考資料 | |
--------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment