docker:Dockerfile構建LNMP平臺

1、dockerfile介紹

 Dockerfile是Docker用來構建鏡像的文本文件,包含自定義的指令和格式。可以通過docker build命令從Dockerfile中構建鏡像。這個過程與傳統分佈式集羣的編排配置過程相似,且提供了一系列統一的資源配置語法。用戶可以用這些統一的語法命令來根據需求進行配置,通過這份統一的配置文件,在不同的平臺上進行分發,需要使用時就可以根據配置文件自動化構建,這解決了開發/運維人員構建鏡像的複雜過程。同時,Dockerfile與鏡像配合使用,使Docker在構建時可以充分利用鏡像的功能進行緩存,大大提升了Docker的使用效率。

 用通俗一點的話來講:dockerfile就是根據自己的需要自定義一個鏡像,就像你寫shell腳本一樣,把一連串的過程或步驟全部寫進dockerfile文件中,一步一步的執行dockerfile文件中你寫的內容。

2、dockerfile指令

docker:Dockerfile構建LNMP平臺

3、build命令

Usage:docker build [OPTIONS] PATH | URL | -

OPTIONS:
-t ,--tag list  #構建後的鏡像名稱
-f, --file string #指定Dockerfiile文件位置

示例:
1,docker build .
2,docker build -t nginx:v10 .
3,docker build -t nginx:v10 -f /path/Dockerfile /path

一般常用第2種方式構建,我們在構建時都會切換到Dockerfile文件的目錄下進行構建,所以不需要指定-f參數。如果還不是很明白的話,下面我們來構建nginx鏡像、php鏡像來理解一下。

4、環境說明

在本文中我都是基於centos 7官方鏡像來構建、nginx和php用的源碼包來構建,如果你不想用源碼包,也可用yum方式構建:

  • nginx,用的是源碼包來構建,版本爲nginx-1.12.1.tar.gz,下載地址http://nginx.org/en/download.html/
  • php,也用的源碼包來構建,版本爲php-5.6.31.tar.gz,下載地址http://php.net/downloads.php

在來看一下目錄結構:

[root@ganbing /]# tree dockerfile/
dockerfile/
├── nginx
│   ├── Dockerfile
│   ├── nginx-1.12.1.tar.gz
│   └── nginx.conf
└── php
    ├── Dockerfile
    ├── php-5.6.31.tar.gz
    └── php.ini

 其中,在dockerfile目錄下創建了兩個目錄(nginx、php),裏面分別存放Dockerfile文件、源碼包。nginx目錄下還放了nginx.conf配置文件,php目錄下也放置了php.ini配置文件。

 有些人會問爲什麼要把nginx.conf、php.ini配置文件放到這裏,有兩個原因,其一,把這兩個默認的配置文件放在這裏可以提前修改好所需要的參數,當容器啓動後,就不需要在進入容器去修改了。當然,我這裏只是練習環境,並未對這兩個文件做任何更改。其二,在實際環境中,這兩個文件是經常需要修改的,單獨拿出來後在啓動容器時你可以把這兩個文件mount到容器中,便於管理。

5、nginx構建

5.1 Dockerfile內容

FROM centos:7
MAINTAINER blog.51cto.com/ganbing
ENV TIME_ZOME Asia/Shanghai

RUN yum -y install gcc gcc-c++ make openssl-devel pcre-devel
ADD nginx-1.12.1.tar.gz /tmp

RUN cd /tmp/nginx-1.12.1 && \
        ./configure --prefix=/usr/local/nginx && \
        make -j 2 && \
        make install

RUN rm -rf /tmp/nginx* && yum clean all && \
        echo "${TIME_ZOME}" > /etc/timezone && \
        ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime

COPY nginx.conf /usr/local/nginx/conf/
WORKDIR /usr/local/nginx/
EXPOSE 80
CMD ["./sbin/nginx","-g","daemon off;"]

來分析一下上面的內容,當你構建時,它會根據你編排好的內容一步一步的執行下去,如果當中的某一步執行不下去,會立刻停止構建。上面的大部分指令都很好理解,在上文中的dockerifle指令中有介紹,最後一個指令我要詳細說明一下:CMD ["./sbin/nginx","-g","daemon off;"]

  • /sbin/nginx 這個沒什麼說的,就是正常啓動nginx服務;
  • -g: 設置配置文件外的全局指令,也就是啓動nginx時設置了daemon off參數,默認參數是打開的on,是否以守護進程的方式運行nginx,守護進程是指脫離終端並且在後臺運行的進程。這裏設置爲off,也就是不讓它在後臺運行。爲什麼我們啓動nginx容器時不讓它在後臺運行呢,docker 容器默認會把容器內部第一個進程,也就是pid=1的程序作爲docker容器是否正在運行的依據,如果docker 容器pid掛了,那麼docker容器便會直接退出。

5.2 nginx.conf內容

......
省略其它默認配置
......

server {
        listen 80;
        server_name localhost;
        root html;
        index index.html index.php;

        location ~ \.php$ {
            root html;
            fastcgi_pass lnmp_php:9000;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }

配置中主要添加了 location ~ .php這一段的內容,其中fastcgi_pass的 lnmp_php,這個是後面啓動php容器時的名稱。瞭解nginx原理的朋友應該能理解,當匹配到php的請求時,它會轉發給lnmp_php這個容器php-fpm服務來處理。正常情況下,如果php服務不是跑在容器中,lnmp_php這個內容一般寫php服務器的Ip地址。

5.3 build構建
nginx源碼包、nginx.conf、Dockerfile都準備好了之後,現在我們可以來用docker build來構建這個鏡像了:

切換到nginx目錄下:
[root@ganbing /]# cd /dockerfile/nginx/
[root@ganbing nginx]# ls
Dockerfile  nginx-1.12.1.tar.gz  nginx.conf

構建:
[root@ganbing nginx]# docker build  -t nginx:1.12.1 .

5.4 查看鏡像是否構建成功

[root@ganbing /]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               1.12.1              19b0dc5eb6bb        15 minutes ago      419MB
centos              7                   ff426288ea90        7 weeks ago         207MB

nginx鏡像已經構建好了,是不是還多了一個centos:7的鏡像呢,這主要是在Dockerfile文件中你的FROM指令寫的是centos:7,如果你的宿主機沒有這個鏡像,它就會從 hub.docker.co 中去pull這個鏡像。

6、php構建

6.1 Dockerfile內容

FROM centos:7
MAINTAINER blog.51cto.com/ganbing
ENV TIME_ZOME Asia/Shanghai
RUN yum install -y gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel
ADD php-5.6.31.tar.gz /tmp/

RUN cd /tmp/php-5.6.31 && \
        ./configure --prefix=/usr/local/php \
        --with-config-file-path=/usr/local/php/etc \
        --with-mysql --with-mysqli \
        --with-openssl --with-zlib --with-curl --with-gd \
        --with-jpeg-dir --with-png-dir --with-iconv \
        --enable-fpm --enable-zip --enable-mbstring && \
        make -j 4 && \
        make install

RUN cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf && \
        sed -i 's/127.0.0.1/0.0.0.0/g' /usr/local/php/etc/php-fpm.conf && \
        sed -i "21a daemonize=no" /usr/local/php/etc/php-fpm.conf && \
        echo "${TIME_ZOME}" > /etc/timezone && \
        ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime

COPY php.ini /usr/local/php/etc/
RUN rm -rf /tmp/php* && yum clean all
WORKDIR /usr/local/php/
EXPOSE 9000
CMD ["./sbin/php-fpm","-c","/usr/local/php/etc/php-fpm.conf"]

上面內容和nginx的Dockerfile風格差不多,也是一步一步的來。先安裝依賴包、解壓、配置並編譯,然後修改下配置文件,啓動php-fpm服務。是不是發現寫Dockerfile挺簡單的,就是把你平時部署php服務的步驟思路寫到這個Dockerfile裏面。

6.2 php.ini內容

這個內容我沒有修改,是默認的配置內容。

6.3 build構建
php源碼包、php.ini、Dockerfile都準備好了之後,現在我們可以來用docker build來構建這個鏡像了:

切換到php目錄下:
[root@ganbing /]# cd /dockerfile/php/
[root@ganbing php]# ls
Dockerfile  php-5.6.31.tar.gz  php.ini

構建:
[root@ganbing nginx]# docker build  -t php:5.6.31 .

6.4 查看鏡像是否構建成功

[root@ganbing php]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 5.6.31              9ed5ccce1735        3 minutes ago       1GB
nginx               1.12.1              19b0dc5eb6bb        About an hour ago   419MB
centos              7                   ff426288ea90        7 weeks ago         207MB

7、運行容器

7.1 創建自定義網絡lnmp

先創建一個自定義網絡,運行ningx、php這些容器的時候加入到lnmp網絡中來:

先來查看一下默認的網絡:
[root@ganbing php]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
8be78de1f4b8        bridge              bridge              local
d77497b635bb        host                host                local
637e45b21ed3        none                null                local

創建:
[root@ganbing php]# docker network  create  lnmp
49fbb89c7e83e5aa817973cab0db06eea9f3090597dc29d2649d79a8c23d8304

7.2 創建php容器

創建容器:

[root@ganbing php]# docker run -itd --name lnmp_php --network lnmp --mount type=bind,src=/app/wwwroot,dst=/usr/local/nginx/html php:5.6.31 
5676b229125a9372c454488a4e55e8542ca761cd682c34f061c051c511df2340

參數說明:
-itd:   在容器中打開一個僞終端進行交互操作,並在後臺運行;
--name: 爲容器分配一個名字lnmp_php;
--network:爲容器指定一個網絡環境爲lnmp網絡;
--mout: 把宿主機的/app/wwwroot目錄掛載到容器的/usr/local/nginx/html目錄,掛載也相當於數據持久化;
php:5.6.31:指定剛纔構建的php鏡像來啓動容器;

查看php容器是否運行:

[root@ganbing php]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5676b229125a        php:5.6.31          "./sbin/php-fpm -c /…"   3 seconds ago       Up 3 seconds        9000/tcp            lnmp_php

7.3 創建nginx容器

創建容器:

[root@ganbing php]# docker run -itd --name lnmp_nginx --network lnmp -p 80:80 --mount type=bind,src=/app/wwwroot,dst=/usr/local/nginx/html nginx:1.12.1 
5468c0acc0246eea4f931361218656721666f1ed4a292bb425f25880880e2b10

上面的參數和創建php容器的參數差不多

查看nginx容器是否運行:

[root@ganbing php]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
5468c0acc024        nginx:1.12.1        "./sbin/nginx -g 'da…"   30 seconds ago      Up 29 seconds       0.0.0.0:80->80/tcp   lnmp_nginx

-l:這個參數的意思是顯示最後創建的容器

7.4 測試訪問

其實到了這一步,我們可以創建一個index.html靜態頁面來訪問一下:

[root@ganbing wwwroot]# echo "Dockerfile lnmp test" > /app/wwwroot/index.html

我們把宿主機的/app/wwwroot目錄已經掛載到容器的/usr/local/nginx/html目錄中,所以直接弄個index.html來測試就行。

用瀏覽器訪問這臺宿主機的ip:
docker:Dockerfile構建LNMP平臺

我們在弄個index.php文件來測試一下:

[root@ganbing wwwroot]# echo "<? phpinfo();" > /app/wwwroot/index.php

訪問一下這個php頁面,是不是也沒問題:
docker:Dockerfile構建LNMP平臺

到了這一步,說明nginx、php的環境是弄好了,下面我們來把mysql數據庫容器跑起來,來完成lnmp的平臺,mysql數據庫我這裏就不用dockerfile來構建了,我直接用官方的鏡像啓動。

7.5 創建mysql容器

在創建容器前,我們創建一個數據卷mysql-volume,把它掛載到mysql容器中,實現數據持久化:

[root@ganbing /]# docker volume  create  mysql-volume
mysql-volume

啓動mysql容器,如果你本地有mysql鏡像,它會引用本的的鏡像,如果沒有它會去docker hub中拉取:

[root@ganbing /]# docker run -itd  --name lnmp_mysql --network lnmp -p 3306:3306 --mount src=mysql-volume,dst=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql --character-set-server=utf8

參數說明:啓動mysql的參數是參考官方鏡像的 https://hub.docker.com/_/mysql/ ,引用官方的mysq鏡像啓動時必須要設定一個root密碼的環境變量.

查看mysql容器是否啓動:

[root@ganbing /]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
871d06d2b425        mysql               "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        0.0.0.0:3306->3306/tcp   lnmp_mysql

創建數據庫wordpress:

docker exec lnmp_mysql sh  -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e"create database wordpress"' 

查看wordpress庫是否創建 :

[root@ganbing /]# docker exec lnmp_mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e"show databases"' 
mysql: [Warning] Using a password on the command line interface can be insecure.
Database
information_schema
mysql
performance_schema
sys
wordpress

查看數據卷是否同步了wordpress庫:

[root@ganbing /]# ls /var/lib/docker/volumes/mysql-volume/_data/
auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem  wordpress

8、下載wordpress博客系統測試lnmp

下載至/app/wwwroot目錄下:

[root@ganbing /]# cd /app/wwwroot/
[root@ganbing wwwroot]# wget https://cn.wordpress.org/wordpress-4.7.4-zh_CN.tar.gz
--2018-03-01 13:52:05--  https://cn.wordpress.org/wordpress-4.7.4-zh_CN.tar.gz
Resolving cn.wordpress.org (cn.wordpress.org)... 198.143.164.252
Connecting to cn.wordpress.org (cn.wordpress.org)|198.143.164.252|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8507412 (8.1M) [application/octet-stream]
Saving to: ‘wordpress-4.7.4-zh_CN.tar.gz’

100%[=========================================================>] 8,507,412   1.08MB/s   in 8.9s   

2018-03-01 13:52:14 (933 KB/s) - ‘wordpress-4.7.4-zh_CN.tar.gz’ saved [8507412/8507412]

解壓並訪問測試:

[root@ganbing wwwroot]# tar -zxvf wordpress-4.7.4-zh_CN.tar.gz

解壓完了之後用瀏覽器訪問:
http://容器宿主機IP/wordpress
docker:Dockerfile構建LNMP平臺

配置wordpress博客:
docker:Dockerfile構建LNMP平臺

docker:Dockerfile構建LNMP平臺

docker:Dockerfile構建LNMP平臺

docker:Dockerfile構建LNMP平臺

9、dockerfile實踐心行

  • 謹慎選擇基礎鏡像
     選擇基礎鏡像時,儘量選擇當前官方鏡像庫中的鏡像。

  • 充分利用緩存
     Docker daemon會順序執行Dockerfile中的指令,而且一旦緩存失效,後續命令將不能使用緩存。爲了有效地利用緩存,需要保證指令的連續性,儘量將所有Dockerfile文件中相同的部分都放在前面,而將不同的部分放在後面。

  • 正確使用ADD和COPY指令
     儘管ADD和COPY用法和作用很相近,但COPY仍是首選。COPY相對ADD而言,功能簡單夠用。

  • RUN指令易讀
     爲了使Dockerfile易讀、易理解和可維護,在使用比較長的RUN指令時可以使用反斜槓\ 分隔多行。

  • 不要在Dockerfile中做端口映射
     Docker的兩個核心概念是可重複性和可移植性,鏡像應該可以在任何主機上運行多次。使用Dockerfile的EXPOSE指令,雖然可以將容器端口映射到主機端口上,但會破壞Docker的可移植性,且這樣的鏡像在一臺主機上只能啓動一個容器。所以端口映射應在docker run 命令中用-p 參數指定。

 #不要在Dockerfile中做如下映射
 EXPOSE 80:8080

 #僅僅暴露80端口,需要另做映射
 EXPOSE 80

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章