Dockerfile 與 Compose 環境搭建學習筆記(一)

大愚Talk發表於2018-06-26

以前一直使用 Vagrant 作為自己的開發環境,並且在上家公司也推行大家採用 Vagrant 作為開發環境,保障公司使用的是同一套開發環境。隨著docker的流行,越來越多的人在docker上執行自己的專案,利用docker也非常方便模擬各種線上叢集,相比虛擬機器效率會更高,不管是搭建還是執行。

網路上關於docker搭建環境的資料非常之多了,但自己一直沒有進行過實踐。紙上得來終覺淺,只有自己動過手之後,才能對相關的概念更熟悉。花了將近2天時間折騰,終於算是把docker的開發環境搭建好了,對他的很多概念也又了更深入的認識。整理一下整個過程,方便以後查漏補缺。

下面就來開啟docker之旅吧,打算利用docker完成以下任務:

  • 基礎的環境搭建:MySQL、Redis、Nginx;
  • 搭建PHP、Golang的開發環境;
  • 搭建MySQL、Redis的主從;
  • 探索一下如何監控docker中的程式。

涉及的命令介紹

這僅僅是操作筆記,不涉及 Docker 原理什麼之類的知識,重點是如何應用。為了後續理解方便,先把用到的相關命令在這裡進行整體介紹。

查詢映象

➜ ~/home/dockerenv >docker search mysql
複製程式碼

上面這個命令就是查詢 mysql 映象。對應的可以將 mysql 替換成其它想要查詢的映象名稱。該命令常用選項是: -s。可以設定搜尋條件:多少個start以上的映象。

➜ ~/home/dockerenv >docker search -s 100 mysql
複製程式碼

搜尋有100個以上start的 mysql 映象。

獲取映象

docker pull centos7
複製程式碼

這個命令會把映象克隆到本地,就像:git clone 一樣的效果。關於什麼是映象、容器之類的概念不在我的講解範疇了。

檢視與刪除映象

➜ ~/home/dockerenv >docker image ls
複製程式碼

會列出當前所有的本地安裝了的映象。看到了有哪些映象,有時候一個映象我們用不到了,想把它幹掉,為硬碟騰騰位置,可以用下面的命令:

➜ ~/home/dockerenv >docker rmi 0d16d0a97dd1 # 編號是 image id
複製程式碼

建立映象 - Dockerfile

docker的映象可以從官方直接拉取,也可也通過 Dockerfile 進行定製,寫好 Dockerfile 檔案後,可以執行下面的命令執行映象。

➜ ~/home/dockerenv >docker build -t nginx:1.14.0 .
複製程式碼

這裡的結尾有個 . 它表示上下文,而不是說 Dockerfile 的路徑。舉例來說,在 Dockerfile 中常常用 Copy 指令,它拷貝的檔案必須要在這個上下文中。

Dockerfile的主要作用是:自己根據基礎映象,重新定製映象,而不是直接從官方倉庫拿現成的使用。

具體含義可以看這裡:yeasy.gitbooks.io/docker_prac…

啟動容器

➜ ~/home/dockerenv >docker run -it --rm php:7 bash
複製程式碼

上面的命令會啟動一個容器,並且分配一個偽終端,退出後容器就會被刪除。

➜ ~/home/dockerenv >docker run -d -p 9000:9000 php:7
複製程式碼

這個命令會在後臺執行一個容器,此容器不會因為退出就被刪除,可以重複進行start、stop操作。

上面兩種容器啟動的操作方式,在我的文章中其實不會出現,我的環境是基於docker-compose + Dockerfile 來搭建的。因為根據最佳實踐:一個容器內部只包含一個程式,像上面我需要安裝:PHP/Golang/Redis/Nginx/Mysql等,就算不算主從也需要啟動5個容器,每次這樣啟動都要累死,還不說需要管理容器之間的互聯。因此我使用Compose來定義和執行多個 Docker 容器的應用。

檢視容器資訊

➜ ~/home/dockerenv >docker inspect a49dfb2e6f45 # image id
複製程式碼

通過該命令可以看到容器的完整資訊,我用這個命令主要是在進行容器互聯的時候,檢查容器的網路與IP相關的情況。

進入容器

➜ ~/home/dockerenv >docker exec -it e8d740a6ac7a bash # image id
複製程式碼

上面的命令可以進入容器,讓你感覺像是 ssh 到了遠端機器一樣的感覺。

停止、啟動

➜ ~/home/dockerenv >docker stop a49dfb2e6f45 # image id
複製程式碼

如果容器是在後臺啟動,可以通過該方式停止容器。停止後可以使用下面的命令啟動容器:

➜ ~/home/dockerenv >docker start a49dfb2e6f45 # image id
複製程式碼

檢視與刪除容器

容器也可以像映象一樣進行檢視

➜ ~/home/dockerenv >docker ps
複製程式碼

上面的命令只會顯示啟動了的映象,如果要檢視所有映象,可以新增 -a 選項。
如果某個容器不需要了,可以使用下面的命令進行刪除:

➜ ~/home/dockerenv >docker rm 0d848bc87fe7  # image id
複製程式碼

容器的刪除並不會影響映象,映象可以繼續用來啟動新的容器。並且如果依賴某個映象建立的容器沒有被刪除,該映象是不能直接刪除的,需要先刪除容器後才能繼續刪除映象。

Compose 中的啟動與停止

針對docker compose啟動與停止用到下面的命令,個人感覺這就是批量操作,畢竟容器太多,一個一個操作太麻煩,容易遺漏等等問題。

批量啟動:

➜ ~/home/dockerenv >docker-compose up -d
複製程式碼

雖然該命令並不是單純的啟動容器,它非常強大,將嘗試自動完成包括構建映象,(重新)建立服務,啟動服務,並關聯服務相關容器的一系列操作。

如果已經建立完了,也可以用下面的命令來啟動已經建立的容器。

➜ ~/home/dockerenv >docker-compose start
複製程式碼

如果想要停止容器可以使用下面的命令:

➜ ~/home/dockerenv >docker-compose stop
複製程式碼

當然這些命令的執行,要在 docker-compose.yml 檔案所在的目錄下執行,否則它也不知道該啟動或關閉哪些容器。

基本用到的命令大概就是上面這些,接下來先說說 docker-compose.yml 檔案的編寫。

Docker Compose構建環境

Docker Compose 可以把多個容器方便的管理起來,也就是所謂的編排技術。

編排技術的核心是 docker-compose.yml 這個模版檔案。它定義了容器叢集裡每一個容器的映象、資料卷掛載路徑、埠、網路等。

以接下來要構建的環境來說明下,下面我將要搭建一個php7的開發環境,需要Nginx/PHP-FPM/MySQL/Redis進行配合。那麼需要啟動4個容器。對應的也需要4個映象。整個環境的目錄結構如下:

├── README.md
├── docker-compose.yml
├── logs
│   └── nginx
├── mysql
│   ├── conf
│   └── data
├── nginx
│   ├── Dockerfile
│   ├── conf
│   └── src
├── php7
│   ├── Dockerfile
│   ├── docker-compose.yml
│   ├── etc
│   ├── extensions
│   └── src
├── redis
│   ├── Dockerfile
│   ├── conf
│   ├── data
│   └── src
├── start.sh
├── stop.sh
└── www
    └── abc
複製程式碼

我的MySQL是直接使用的官方提供的映象資源,而Redis/Nginx/PHP為了做定製化,我採用Dockerfile進行自定義。接下來按照每一個獨立的服務分別進行一下說明。

MySQL服務

dev.mysql.srv:
  image: mysql:5.7.22
  volumes:
    - ./mysql/data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d
  ports:
    - "3307:3306"
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: 123123
  networks:
    - default
複製程式碼
  • image:是制定依賴的映象,這裡是Docker提供的映象資源;
  • volumes:資料卷所掛載路徑設定,主要是MySQL的資料儲存的路徑設定與配置檔案的設定。它的主要作用是持久化資料,避免容器銷燬後內部資料丟失;
  • ports:暴露到宿主機的埠。這個沒什麼太多說的,就是為了可以在宿主機訪問到容器內部的服務;
  • restart:該命令是設定容器如果在某種情況下(非認為)退出了,容器重啟的策略;
  • environment:設定映象的環境變數,你可以進入映象通過:echo $MYSQL_ROOT_PASSWORD檢視其值;
  • networks:設定網路,讓所有的容器在一個網路中,方便容器互聯互通。

這裡還有一個點需要注意,dev.mysql.srv ,是我為mysql服務取的名字。取一個好的名字,非常便於後續容器互聯的使用,比如這個名字,如果php程式碼需要填寫mysql的host。我則可以直接使用它。

其它服務

剩下的三種服務配置方式基本上大同小異。我放在一起說明。

dev.nginx.srv:
  image: lei_nginx:1.14.0
  build: ./nginx
  volumes:
    - ./nginx/conf:/home/work/app/nginx/conf
      - ./www:/home/work/www
  ports:
    - "80:8080"
      - "443:443"
  restart: always
  networks:
    - default
  depends_on:
      - dev.php-fpm.srv
dev.redis.srv:
  image: lei_redis:3.2.11
  build: ./redis
  volumes:
    - ./redis/conf:/home/work/app/redis/conf
      - ./redis/data:/home/work/app/redis/data
  ports:
      - "6379:6379"
  restart: always
  networks:
      - default
dev.php-fpm.srv:
  image: lei_php:7.2.6
  build: ./php7
  volumes:
    - ./php7/etc:/home/work/app/php/etc
    - ./www:/home/work/www
  ports:
    - "9000:9000"
  restart: always
  networks:
    - default
複製程式碼

這裡與MySQL最大的一個區別是多了一個 build 選項。這就是上面說到的這三個映象都是我用Dockerfile定製的有關。你可以在對應的 build 指定的目錄下看到 Dockerfile 這個檔案。

另外一個需要注意的地方是Nginx中配置的 depends_on 選項,他的作用是指定依賴,因為Nginx中我配置了php-fpm。所以它啟動前要確保php-fpm已經啟動後,他才能正常的啟動。

啟動

為了減少太多概念的東西,你可以先直接從github拉取這部分配置,然後執行

➜ ~/home/dockerenv >./start.sh
Starting dockerenv_dev.php-fpm.srv_1 ... done
Starting dockerenv_dev.redis.srv_1   ... done
Starting dockerenv_dev.mysql.srv_1   ... done
Creating dockerenv_dev.nginx.srv_1   ... done
複製程式碼

如果你是第一次執行 start.sh ,他還會去docker hub上拉取映象,以及根據Dockerfile來定製映象。所以會有非常多的輸出資訊。

然後訪問:http://localhost 。應該就能夠看到 phpinfo() 輸出的資訊。

總結

經過自己的熟悉,對基本的docker命令,以及docker的三個基礎概念:倉庫、映象、容器有了充分的認識。利用 docker compose 搭建一個環境後,對於容器的互聯也有了更深刻的體會,並且經過這種一個容器執行一個程式的方式,對系統也有了一些更深的認識。在利用Dockerfile定製映象的過程中,通過反覆的 build 映象,對理解容器的分層、如何確保映象體積更小方面有了相當多的實踐,特別是在ENTRYPOINT的設定上,認識到了docker的啟動流程。

由於篇幅限制,把 Dockerfile 的內容在拆出一篇來進行說明,以及把遇到的一些問題也進行一些整理。

我的docker環境:github.com/helei112g/d…

以後換機裝換機,再也不擔心了

微信公眾號:
pub

參考資料:


相關文章