Docker搭建可一鍵部署的多域名LNMP環境
原文連結:https://www.awaimai.com/2120.html
本文介紹在Docker容器中,快速部署LNMP環境的完整步驟。
最終完成的環境我們暫且叫:DNMP(即 Docker + Nginx + MySQL + PHP)。
最終實現一鍵部署LNMP環境的目的,特點:
完全開源
支援多版本PHP切換(PHP5.4、PHP5.6、PHP7.2...)
支援繫結任意多個域名
支援HTTPS和HTTP/2
PHP原始碼位於host中
MySQL data位於host中
所有配置檔案可在host中直接修改
所有日誌檔案可在host中直接檢視
內建完整PHP擴充套件安裝命令
本站實際使用,確保100%可行
實現一次配置,可在任何支援Docker系統使用
1 快速使用
1、安裝git、docker和docker-compose。
2、使用git下載完整程式碼:
$ gitclonehttps://github.com/yeszao/dnmp.git
3、用docker-compose命令啟動容器,首次使用需要下載映象,會稍慢:
$ docker-compose up
4、然後在瀏覽器中訪問localhost,就可以看到如下頁面:
5、原始碼在:./www/site1/目錄下。
2 安裝docker和docker-compose
具體安裝步驟:
注意:Docker安裝要求Linux3.10以上版本,用uname-a命令可檢視到。
安裝之後,可檢視版本:
$ docker -v
$ docker-compose -v
然後把當前使用者加到docker使用者組裡面:
$ sudo gpasswd-a${USER}docker
就不用每次啟動Docker都得加sudo了。
注意,執行gpasswd命令之後要重新登陸才有效。
3 使用國內映象倉庫
在沒有梯子的情況下,Docker預設從Docker Hub倉庫下載映象,完整的LNMP映象估計需要一兩天時間。
所以只能換個途徑,比如使用阿里雲的加速倉庫。
首先註冊一個阿里雲賬號,然後訪問阿里雲的Docker映象倉庫,能找到加速器地址。
對於Docker 1.10+,開啟配置檔案/etc/docker/daemon.json(沒有時新建該檔案):
{"registry-mirrors": ["https://6evg8u3r.mirror.aliyuncs.com"]}
以上是我的加速地址。
然後重啟Docker Daemon:
sudosystemctl daemon-reloadsudo systemctl restart docker
就可以了。
4 目錄說明
大致框架如下:
(圖片使用UMLet繪製,下載原檔案)
4.1 目錄結構
目錄結構如下:
.├──docker-compose.yml容器啟動配置檔案├──DockerfilePHP-FPM構建配置檔案├──conf配置目錄│ ├──mysqlMySQL配置檔案目錄│ │ └──my.cnfMySQL配置檔案│ ├──nginxNginx配置檔案目錄│ │ ├──conf.d站點配置檔案目錄│ │ │ ├──certsSSL認證檔案、金鑰和加密檔案目錄│ │ │ │ └──site2站點2的認證檔案目錄│ │ │ ├──site1.conf站點1Nginx配置檔案│ │ │ └──site2.conf站點2Nginx配置檔案│ │ └──nginx.confNginx通用配置檔案│ └──phpPHP配置目錄│ ├──php-fpm.dPHP-FPM配置目錄│ │ └──www.confPHP-FPM配置檔案│ └──php.iniPHP配置檔案├──log日誌目錄│ ├──mysqlMySQL日誌目錄│ ├──nginxNginx日誌目錄│ └──php-fpmPHP-FPM日誌目錄├──mysqlMySQL資料檔案目錄└──www站點根目錄 ├──site1站點1根目錄 └──site2站點2根目錄
4.2 站點部署
本文有預設加了兩個站點:www.site1.com(同localhost)和www.site2.com。
要在本地訪問這兩個域名,需要修改你的hosts檔案,新增以下兩行:
127.0.0.1www.site1.com127.0.0.1www.site2.com
其中,www.site2.com為支援SSL/https和HTTP/2的示例站點。
因為站點2的SSL採用自簽名方式,所以瀏覽器有安全提示,繼續訪問就可以了,自己的站點用第三方SSL認證證書替換即可。
如果只用到站點1,把站點2相關的目錄和配置檔案刪除:
./conf/nginx/conf.d/certs/site2/./conf/nginx/conf.d/site2.conf./www/site2/
重啟容器內的Nginx生效:
dockerexec-it dlnmp_nginx_1 nginx-sreload
4.3 HTTPS使用
在容器中我們也是可以用HTTPS的,具體的配置請參考如下檔案:
./conf/nginx/conf.d/site2.conf
如果是自簽名,可以用廖雪峰提供的一個自動生成認證檔案、私鑰指令碼:gencert.sh,
這個指令碼已經放在專案中,在這個目錄下:
./conf/nginx/conf.d/certs/site2/
在Bash中輸入:
$ ./gencert.sh
輸入一次域名,和幾次密碼(內容隨意)後,就會生成幾個認證檔案。
其中自簽名情況不需要.csr和.origin.key字尾的檔案。
然後修改Nginx配置檔案,配置SSL支援就可以了。
5 docker-compose.yml檔案
如下是docker容器的執行配置docker-compose.yml的內容:
nginx:image:nginx:alpineports:-"80:80"-"443:443"volumes:- ./www/:/var/www/html/:rw- ./conf/nginx/conf.d:/etc/nginx/conf.d/:ro- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./log/nginx/:/var/log/nginx/:rwlinks:- php-fpm:fpmphp-fpm:build:.expose:-"9000"volumes:- ./www/:/var/www/html/:rw- ./conf/php/php.ini:/usr/local/etc/php/php.ini:ro - ./conf/php/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf:rw - ./log/php-fpm/:/var/log/php-fpm/:rwlinks:-mysql:mysql -redis:redismysql:image:mysql:latestports:-"3306:3306"volumes:- ./conf/mysql/my.cnf:/etc/mysql/my.cnf:ro - ./mysql/:/var/lib/mysql/:rw- ./log/mysql/:/var/log/mysql/:rwenvironment:MYSQL_ROOT_PASSWORD:"123456"redis:image:redis:latestports:-"6379:6379"
這裡我們用了nginx的alpine映象,以及php-fpm和MySQL的最新映象。
這裡預設加了redis容器,不需要的話可以把檔案的最後4行以及php-fpm塊下的-redis:redis刪除。
5.1 為什麼用nginx:alpine?
因為相比nginx:latest,nginx:alpine有幾點優勢:
用的是最新版nginx映象,功能與nginx:latest一模一樣
alpine映象用的是Alpine Linux核心,比ubuntu核心要小很多。
nginx:alpine預設支援http2。
如要進入alpine容器,命令是(後面的路徑不是/bin/bash):
$ dockerexec-it dnmp_nginx_1 /bin/sh
5.2 站點根目錄掛載
為什麼站點根目錄在Nginx和PHP-FPM都這樣掛載?
./www/:/var/www/html/
我們知道,Nginx配置都有這樣一項:
fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;
其中,$document_root就是server塊下root所指的路徑:
server{#...root/var/www/html;#...}
這裡$document_root就是/var/www/html。
如果Nginx和PHP-FPM在同一主機,Nginx會通過9000埠把這個目錄值和指令碼URI傳給PHP-FPM。
PHP-FPM再通過9000埠接收Nginx發過來的目錄值和指令碼URI,發給PHP解析。
PHP收到後,就到指定的目錄下查詢PHP檔案並解析,完成後再通過9000埠返回給Nginx。
如果Nginx和PHP-FPM在同一個主機裡面,PHP就總能找到Nginx指定的目錄。
但是,如果他們在不同的容器呢?
未做任何處理的情況,Nginx容器中的站點根目錄,PHP-FPM容器肯定不存在。
所以,這裡需要保證Nginx和PHP-FPM都掛載了Host的./www/,並且都掛載在容器的:/var/www/html。
(當然,你也可以指定別的目錄,確保統一即可)
5.3 修改docker-compose.yml檔案之後?
如果容器已經生成,回頭再編輯docker-compose.yml,用
docker-compose up
命令會直接啟動原來的容器,修改的內容不會體現在啟動的容器裡。
所以,要使修改的docker-compose.yml生效,需要以下4步:
$ docker stop dnmp_nginx_1# 第一步:停止容器$ docker rm dnmp_nginx_1# 第二步:刪除容器# !!第三步:重啟Docker服務!!$ docker-compose up -d --no-deps --build mysql# 第四步:重新啟動容器
其中最後一條命令引數作用:
-d:後臺執行
--no-deps:不啟動link的容器
--build:啟動容器前先構建映象
6 Dockerfile檔案
因為PHP-FPM構建稍微複雜,涉及到很多擴充套件。
所以單獨用Dockerfile檔案構建PHP-FPM:
FROMphp:fpm## Copy sources.list to container.## Here we use 163.com sources list.## PHP 5.6.31+ should use jessie sources list## PHP 7.2.0+ should use stretch sources list## For more please check:## PHP official docker repository: https://hub.docker.com/r/library/php/#COPY ./files/sources.list.stretch /etc/apt/sources.list#COPY ./files/sources.list.jessie /etc/apt/sources.list## Update UbuntuRUN apt-get update## mcryptRUN apt-get install -y libmcrypt-devRUN docker-php-ext-install mcrypt## GDRUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-devRUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/RUN docker-php-ext-install -j$(nproc) gd## IntlRUN apt-get install -y libicu-devRUN docker-php-ext-install -j$(nproc) intl## GeneralRUN docker-php-ext-install zipRUN docker-php-ext-install pcntlRUN docker-php-ext-install opcacheRUN docker-php-ext-install pdo_mysqlRUN docker-php-ext-install mysqliRUN docker-php-ext-install mbstring## ...
完整Dockerfile請移步本專案GitHub倉庫。
7 nginx配置檔案
這裡,我們還需要稍微修改nginx配置檔案:
location~ \.php${fastcgi_passfpm:9000;fastcgi_indexindex.php;includefastcgi_params;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;}
這裡,我們僅需把fastcgi_pass改成:fpm:9000。
也就是,PHP-FPM的偵聽主機改成:NginxlinksPHP-FPM容器的別名,在docker-compose.yml檔案裡面我們設定為fpm。
這樣Nginx容器啟動的時候,就會自動修改自己的/etc/hosts,讓fpm指向php-fpm容器的IP。
修改之後,重啟容器中的nginx:
$ dockerexecdlnmp_nginx_1 nginx-sreload
其中,dlnmp_nginx_1是容器的名稱,也可以指定容器的ID。
8 站點根目錄寫許可權
有時候,我們的PHP程式碼需要某個目錄的寫許可權。
比如,Wordpress的wp-content/uploads目錄,只有寫許可權我們才能正常上傳檔案。
預設的,容器中的/var/www/html目錄屬於root,我們需要修改為www-data,PHP才能正常寫目錄。
先進入到容器中:
$ dockerexec-it dlnmp_php-fpm_1 /bin/bash
然後修改目錄許可權:
$ chown -R www-data:www-data /var/www/html
這樣PHP就能正常讀寫目錄了。
9 資料庫
9.1 使用MySQL
在docker-compose.yml檔案中,我們指定了MySQL資料庫root使用者的密碼為123456。
所以,我們就可以在主機中通過:
$ mysql -h127.0.0.1-u root -p
輸入密碼,就可以進入MySQL命令列。
說明:這裡MySQL的連線主機不能用localhost,因為MySQL客戶端預設使用unix socket方式連線,應該直接用本地IP。
在PHP程式碼中的使用方式與在主機中使用稍有不同,如下:
$pdo =newPDO('mysql:host=mysql;dbname=site1','root','123456');
其中,host的值就是在docker-compose.yml裡面指定的MySQL容器的名稱。
這是因為PHP程式碼是在FPM容器中,FPM容器啟動時會自動在/etc/hosts中加上:
172.17.0.2mysql11e55f91c4c3dlnmp_mysql_1
就是說,mysql自動指向了MySQL容器動態生成的IP。
9.2 使用Redis
Redis使用和MySQL類似。
在主機和容器內部都通過地址127.0.0.1,埠6379訪問。
PHP則是跨容器訪問,host引數用redis(links指定的名稱),埠用6379。
Docker相關的有用文章: