docker入門講解
最近公司在提倡使用 docker,之前只是簡單瞭解了一下基礎語法,在本機上搭建了一個 php 容器湊合著用,週末在家沒事所以準備把這塊再繼續加深一下理解,用比較通俗的語言來闡述一下自己的理解。本篇文章適合小白及入門閱讀使用,目的是讓對 docker 不熟悉甚至沒有用過的人能夠有一個直觀的理解。
1.docker是什麼
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的映象中,然後釋出到任何流行的 Linux 或 Windows 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面。
docker 官方的解釋,看起來有點像我們之前用過的虛擬機器,但是和虛擬機器還是有些區別的:
- 虛擬機器模擬的是整臺機器包括硬體,每臺虛擬機器都有自己的作業系統,虛擬機器一旦開啟預分配給他的資源將全部佔用。
- 容器與我們的宿主機共享硬體資源及作業系統,可以實現資源動態分配,容器包含應用及依賴包,而且與其他容器共享核心。容器在宿主機作業系統中,在使用者空間以分離的程式執行。
這是引用網上的對容器和虛擬機器區別的一些概述,以我個人的理解來看,容器比虛擬機器可以管理的粒度更小,更適合我們作為日常開發及應用的部署,而且比虛擬機器更輕,對宿主機硬體的要求也更低。
2.docker能用來做什麼
如果站在php開發的角度來看的話,我相信大部分人都對更換開發機,部署伺服器執行環境感到頭大,那意味著你將要耗費大量的時間,對應用進行下載、安裝以及配置,一不小心幾個小時就過去了,尤其是如果在本地除錯需要切換不同PHP版本進行程式除錯。當然你可以選擇使用整合環境來進行部署,不過安裝之後的自定義配置、擴充套件的安裝還是免不了。(很久之前本地開發是使用phpstudy的,確實是很方便,不知道現在是不是有更好的工具)
那麼docker可以很好的解決這個問題,我們可以把自己已經構建好的一套執行環境打包成映象,下次再使用的時候直接下載映象進行安裝即可使用,而且可以安裝不同的版本,滿足我們對任意環境的組合要求,看這個樣子是不是有點像我們安裝作業系統時直接從映象安裝一樣?差不多的道理, 只不過docker可以將映象封裝的粒度更細,可以將一個php、nginx或任意你想要的應用封裝起來,這樣我們在使用的時候選擇性就更多一些。
3.基礎語法介紹
我們先介紹幾個簡單的命令:
- docker pull -- 從遠端倉庫將映象下載至本地
- docker run -- 執行一個容器
- docker exec -- 對映象進行操作,常用的就是我們進入到映象中進行配置(有點像我們遠端登入一個linux伺服器)
上面三條指令就可以幫助我們搭建一個簡單容器進行使用,下面是幾條常用的常看容器的命令:
- docker images -- 常看本地映象
- docker ps -- 檢視容器,預設只檢視已啟動的,加入 "-a" 引數可以檢視所有
- docker start|stop|rm|rmi -- 容器的相關操作,分別對應: 開啟|停止|刪除容器|刪除映象
4.一個簡單的例子
4.1下載一份ubuntu的最新映象
docker pull ubuntu
4.2執行容器指定映象
docker run ubuntu echo 'Hello'
可以看到命令列下方列印出‘Hello’字樣,然後我們使用docker ps
命令檢視並沒有我們剛才的那個容器,這是因為容器在執行完 echo 命令後沒有其他的可執行命令後就會退出,這怎麼行?我們使用容器主要就是想讓他保持執行,所以我們需要想個辦法讓容器始終保持執行
4.3讓容器始終保持執行
docker run -itd --name test-ubuntu ubuntu
引數說明:
- t - 讓docker分配一個偽終端並繫結到容器的標準輸入上
- i - 讓容器的標準輸入保持開啟
- d - 讓容器後臺執行
- name - 給容器命名,否則就是系統隨機生成的一個名字,不好記,這裡我們給他命名叫:test-ubuntu
it
引數可以讓容器始終保持一個偽終端等待使用者的輸入,但是因為加了d
引數,使容器進入後臺執行了,所以不會有人輸入到容器,這樣容器就一直保持執行了。可以使用docker ps
命令檢視一下哦。
4.4進入容器
docker exec -it test-ubuntu /bin/bash
說明:使用exec
指令,在容器名稱後的參數列示進入容器後執行的命令,這裡我們使用base命令處理器,以達到我們和容器互動的效果。
這樣我們就進入容器中了,可以看到基礎的映象中很多的命令都不存在,需要我們一一進行安裝,我這裡使用的是ubuntu,所以可以執行apt-get update && apt-get install xxx 來進行安裝。
到這裡docker的基礎使用我們已經介紹完了,下面我們來實戰一下,建立一個我們平時使用的php容器。
5.使用docker搭建一個php-fpm容器
5.1首先我們從遠端倉庫下載一份php-fpm映象
docker pull php:7.3.5-fpm
說明:冒號後面跟著映象的tag,不寫預設就是最新的,但可能不是fpm,我這裡選擇的是7.3.5的php-fpm版本
5.2執行一個容器
docker run -itd -p 9001:9000 -v /Users/admin/Site/php7.3.5:/data --name php-test php:7.3.5-fpm
引數說明:
- p - 格式:
-p [宿主機埠]:[容器埠]
指定宿主機與容器之間的埠對映,我這裡使用的是9001對應容器的9000埠 - v - 格式:
-v [宿主機目錄]:[容器目錄]
掛載一個宿主機的目錄,這裡我掛載的是php程式碼,這樣我們在宿主機修改php程式碼時,就可以同步到容器中了。其實php-fpm的配置檔案相關的也可以使用-v
引數來掛載,省的每次修改都進入容器裡改了,這個示例我沒加,感興趣的同學可以下去自己加一下。
這樣我們就建立了一個php-7.3.5版本的容器
5.3進入容器
docker exec -it php-test /bin/bash
進入容器後可以使用php -v
來檢視php版本,如果需要安裝擴充套件可以使用pecl install redis
來進行安裝(這裡只是舉例redis,只是這樣會安裝失敗,需提前安裝所需依賴,你們自己想辦法 [滑稽臉])。
因為我們下載的是php映象,所以一些此映象啟動後會預設啟動php-fpm作為1號程式,也就是說如果我們殺死php-fpm程式,此容器就會關閉。
5.4使用nginx關聯容器的php-fpm使用
新建一個測試站點,配置檔案如下(路徑改成你自己的,主要關注fpm那裡的設定即可):
server {
# 監聽埠
listen 80;
# 域名設定
server_name www.dockertest.com;
root /Users/admin/Site/php7.3.5/; # 該項要修改為你準備存放相關網頁的路徑,如果存在fast-cgi的root欄位,這裡貌似就沒效果了
location / {
index index.php index.html;
# 開啟目錄瀏覽功能,可以列出整個目錄
autoindex on;
}
#proxy the php scripts to php-fpm
location ~ \.php$ {
# fastcgi配置
# 指定是否傳遞4xx和5xx錯誤資訊到客戶端
fastcgi_intercept_errors on;
# 指定FastCGI伺服器監聽埠與地址,可以是本機或者其它,這裡是重點,需要指定php-fpm容器的埠和根目錄
fastcgi_pass 127.0.0.1:9001;
root /data;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
這樣,我們執行www.dockertest.com時,就可以訪問到php-test容器中/data/index.php檔案了。
用一張圖來表示容器在宿主機裡的狀態:
6.進階使用:Dockerfile
好了,到了這裡我們已經瞭解到如何去搭建一個容器以及容器的基本使用了,可是有一個問題,那就是雖然我們的容器執行起來了,但是想要真正的去深度使用他還需要安裝各種常用命令以及依賴,比如vim指令、php的各種依賴等,因為倉庫的映象資源是不包含這些指令的,所以還需要我們自己來處理,那麼有沒有什麼方法可以不用每次構建容器都去做這些重複的配置呢?當然有,就是Dockerfile。
Dockerfile是一個包含用於組合映像的命令的文字文件。可以使用在命令列中呼叫任何命令。 Docker通過讀取Dockerfile中的指令自動生成映像。
說白了,其實就是將我們想要構建的容器中使用到的各種應用和依賴進行一個打包,讓程式自動的來執行。寫好Dockerfile後使用build指令即可。
docker build -t php7.3.5 .
其中 php7.3.5 是構建完成之後容器的名稱, 「.」表示執行當前目錄的Dockerfile,所以命名不要寫錯,必須是「Dockerfile」
7.Dockerfile引數解釋
Dockerfile 一般分為四部分:基礎映象資訊、維護者資訊、映象操作指令和容器啟動時執行指令,’#’ 為 Dockerfile 中的註釋。
Docker以從上到下的順序執行Dockerfile的指令。為了指定基本映像,第一條指令必須是FROM。一個宣告以#字元開頭則被視為註釋。可以在Docker檔案中使用RUN,CMD,FROM,EXPOSE,ENV等指令。
在這裡列出了一些常用的指令。
欄位名稱 | 解釋 |
---|---|
FROM | 指定基礎映象,必須為第一個命令 |
MAINTAINER | 維護者資訊 |
RUN | 構建映象時執行的命令 |
ADD | 將本地檔案新增到容器中,tar型別檔案會自動解壓(網路壓縮資源不會被解壓),可以訪問網路資源,類似wget |
COPY | 功能類似ADD,但是是不會自動解壓檔案,也不能訪問網路資源 |
CMD | 構建容器後呼叫,也就是在容器啟動時才進行呼叫。 |
ENTRYPOINT | 配置容器,使其可執行化。類似於CMD,但如果使用docker run 配合執行指令時,會覆蓋CMD的命令,ENTRYPOINT的不會被覆蓋,始終會執行 |
EXPOSE | 指定於外界互動的埠 |
VOLUME | 用於指定持久化目錄,注意這個和docker run -v 引數不一樣,這裡是標註此容器中哪個目錄是作為掛載卷存在的,這樣別的容器可以配合使用--volumes-from [containerId] 就可以將掛載的卷同步過來了 |
WORKDIR | 工作目錄,類似於cd命令 |
8.使用Dockerfile搭建php-fpm
這裡就不多寫了,直接呈上php-fpm的Dockerfile檔案,僅供大家參考:
FROM php:7.3.5-fpm
MAINTAINER liyan
#安裝環境系統命令
RUN apt-get update && apt-get install -y \
vim \
libssl-dev
#安裝PHP擴充套件
RUN pecl install igbinary \
redis-4.0.2 \
swoole
#配置php.ini
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
ln -s /usr/local/etc/php/php.ini /etc/php.ini && \
echo "extension=igbinary.so\nextension=redis.so\nextension=swoole.so" >> /etc/php.ini
EXPOSE 9300
VOLUME ["/data"]
WORKDIR /data
9.使用Dockerfile搭建nginx+php環境
這裡將nginx+php都放在同一個容器中了,其實按理說應該獨立開來更靈活,一個nginx可以對應N個php,我也是閒的蛋疼,都弄一塊用supervisor來管理。感興趣的同學也可以玩玩。
FROM ubuntu
MAINTAINER liyan
#建立使用者
RUN useradd www
#安裝依賴
RUN apt-get update && \
apt-get install -y \
vim \
make \
gcc \
g++ \
openssl \
curl \
libcurl4-openssl-dev \
libbz2-dev \
libxml2-dev \
libjpeg-dev \
libpng-dev \
libfreetype6-dev \
libzip-dev \
libssl-dev \
unzip \
supervisor
#拷貝相關依賴
ADD nginx-1.16.1.tar.gz /usr/local/src
ADD php-7.3.11.tar.xz /usr/local/src
ADD zlib-1.2.11.tar.gz /usr/local/src
ADD pcre-8.43.tar /usr/local/src
COPY supervisord.conf /etc/supervisor/
COPY conf.d /etc/supervisor/conf.d/
#安裝nginx依賴
RUN cd /usr/local/src/zlib-1.2.11 && ./configure && make && make install
#安裝nginx
RUN cd /usr/local/src/nginx-1.16.1 && \
./configure --with-pcre=/usr/local/src/pcre-8.43 && \
make && make install && \
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/
#安裝PHP
RUN cd /usr/local/src/php-7.3.11 && ./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--enable-fpm \
--with-fpm-user=www \
--with-fpm-group=www \
--with-mysqli \
--with-pdo-mysql \
--with-iconv-dir \
--with-freetype-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib \
--with-libxml-dir=/usr \
--enable-xml \
--disable-rpath \
--enable-bcmath \
--enable-shmop \
--enable-sysvsem \
--enable-inline-optimization \
--with-curl \
--enable-mbregex \
--enable-mbstring \
--enable-ftp \
--with-gd \
--with-openssl \
--with-mhash \
--enable-pcntl \
--enable-sockets \
--with-xmlrpc \
--enable-zip \
--enable-soap \
--without-pear \
--with-gettext \
--disable-fileinfo \
--enable-maintainer-zts && \
make && make install &&\
ln -s /usr/local/php/sbin/php-fpm /usr/local/bin/
EXPOSE 80
VOLUME ["/data"]
WORKDIR /data
ENTRYPOINT ["supervisord", "-nc", "/etc/supervisor/supervisord.conf"]