1. 程式人生 > >Docker搭建可一鍵部署的多域名LNMP環境

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相關的有用文章: