Docker LNMP環境搭建


原文地址:https://www.awaimai.com/2120.html

本文介紹如何使用Docker容器,快速部署LNMP環境。
最終完成的環境我們稱為:DNMP(即 Docker + Nginx + MySQL + PHP)。

最終實現一鍵部署LNMP環境的目的,該環境特點:

  1. 完全開源
  2. 支持多版本PHP切換(PHP5.4、PHP5.6、PHP7.2...)
  3. 支持綁定任意多個域名
  4. 支持HTTPS和HTTP/2
  5. PHP源代碼位於host
  6. MySQL data位於host
  7. 所有配置文件可在host中直接修改
  8. 所有日志文件可在host中直接查看
  9. 內置完整PHP擴展安裝命令
  10. 本站實際使用,確保100%可用
  11. 實現一次配置,Windows、Linux、MacOs皆可用

github倉庫地址https://github.com/yeszao/dnmp

1 快速使用

1、安裝gitdockerdocker-compose

2、使用git下載完整代碼:

$ git clone https://github.com/yeszao/dnmp.git

3、用docker-compose命令啟動容器,首次使用需要下載鏡像,會稍慢:

$ docker-compose up

4、然后在瀏覽器中訪問localhost,就可以看到如下頁面:

5、源代碼在:./www/site1/ 目錄下。

2 安裝docker和docker-compose

具體安裝步驟:

注意:Docker安裝要求Linux 3.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:

sudo systemctl daemon-reload
sudo systemctl restart docker

就可以了。

Docker 1.10以下請看:https://yq.aliyun.com/articles/29941

4 目錄說明

大致框架如下:

(圖片使用UMLet繪制,下載原文件

4.1 目錄結構

目錄結構如下:

.
├── docker-compose.yml 容器啟動配置文件 ├── Dockerfile PHP-FPM構建配置文件 ├── conf 配置目錄 │   ├── mysql MySQL配置文件目錄 │   │   └── my.cnf MySQL配置文件 │   ├── nginx Nginx配置文件目錄 │   │   ├── conf.d 站點配置文件目錄 │   │   │   ├── certs SSL認證文件、密鑰和加密文件目錄 │   │   │   │   └── site2 站點2的認證文件目錄 │   │   │   ├── site1.conf 站點1 Nginx配置文件 │   │   │   └── site2.conf 站點2 Nginx配置文件 │   │   └── nginx.conf Nginx通用配置文件 │   └── php PHP配置目錄 │   ├── php-fpm.d PHP-FPM配置目錄 │   │   └── www.conf PHP-FPM配置文件 │   └── php.ini PHP配置文件 ├── log 日志目錄 │   ├── mysql MySQL日志目錄 │   ├── nginx Nginx日志目錄 │   └── php-fpm PHP-FPM日志目錄 ├── mysql MySQL數據文件目錄 └── www 站點根目錄 ├── site1 站點1根目錄 └── site2 站點2根目錄

4.2 站點部署

本文有默認加了兩個站點:www.site1.com(同localhost)和www.site2.com

要在本地訪問這兩個域名,需要修改你的hosts文件,添加以下兩行:

127.0.0.1 www.site1.com 127.0.0.1 www.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生效:

docker exec -it dlnmp_nginx_1 nginx -s reload

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:alpine ports: - "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/:rw links: - php-fpm:fpm php-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/:rw links: - mysql:mysql - redis:redis mysql: image: mysql:latest ports: - "3306:3306" volumes: - ./conf/mysql/my.cnf:/etc/mysql/my.cnf:ro - ./mysql/:/var/lib/mysql/:rw - ./log/mysql/:/var/log/mysql/:rw environment: MYSQL_ROOT_PASSWORD: "123456" redis: image: redis:latest ports: - "6379:6379"

這里我們用了nginx的alpine鏡像,以及php-fpm和MySQL的最新鏡像。

這里默認加了redis容器,不需要的話可以把文件的最后4以及php-fpm塊下的- redis:redis刪除。

5.1 為什么用nginx:alpine?

因為相比nginx:latestnginx:alpine有幾點優勢:

  1. 用的是最新版nginx鏡像,功能與nginx:latest一模一樣
  2. alpine鏡像用的是Alpine Linux內核,比ubuntu內核要小很多。
  3. nginx:alpine默認支持http2。

Alpine的更多請看《Alpine Linux,一個只有5M的Docker鏡像》。

如要進入alpine容器,命令是(后面的路徑不是/bin/bash):

$ docker exec -it dnmp_nginx_1 /bin/sh

5.2 站點根目錄掛載

為什么站點根目錄在Nginx和PHP-FPM都這樣掛載?

./www/:/var/www/html/

我們知道,Nginx配置都有這樣一項:

fastcgi_param SCRIPT_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:

FROM php: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 Ubuntu RUN apt-get update ## mcrypt RUN apt-get install -y libmcrypt-dev RUN docker-php-ext-install mcrypt ## GD RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ RUN docker-php-ext-install -j$(nproc) gd ## Intl RUN apt-get install -y libicu-dev RUN docker-php-ext-install -j$(nproc) intl ## General RUN docker-php-ext-install zip RUN docker-php-ext-install pcntl RUN docker-php-ext-install opcache RUN docker-php-ext-install pdo_mysql RUN docker-php-ext-install mysqli RUN docker-php-ext-install mbstring ## ...

完整Dockerfile請移步本項目GitHub倉庫

7 nginx配置文件

這里,我們還需要稍微修改nginx配置文件:

location ~ \.php$ { fastcgi_pass fpm:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }

這里,我們僅需把fastcgi_pass改成:fpm:9000

也就是,PHP-FPM的偵聽主機改成:Nginx links PHP-FPM容器的別名,在docker-compose.yml文件里面我們設置為fpm

這樣Nginx容器啟動的時候,就會自動修改自己的/etc/hosts,讓fpm指向php-fpm容器的IP。

修改之后,重啟容器中的nginx:

$ docker exec dlnmp_nginx_1 nginx -s reload

其中,dlnmp_nginx_1是容器的名稱,也可以指定容器的ID。

8 站點根目錄寫權限

有時候,我們的PHP代碼需要某個目錄的寫權限。

比如,Wordpress的wp-content/uploads目錄,只有寫權限我們才能正常上傳文件。

默認的,容器中的/var/www/html目錄屬於root,我們需要修改為www-data,PHP才能正常寫目錄。

先進入到容器中:

$ docker exec -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 -h 127.0.0.1 -u root -p

輸入密碼,就可以進入MySQL命令行。

說明:這里MySQL的連接主機不能用localhost,因為MySQL客戶端默認使用unix socket方式連接,應該直接用本地IP。

在PHP代碼中的使用方式與在主機中使用稍有不同,如下:

$pdo = new PDO('mysql:host=mysql;dbname=site1', 'root', '123456');

其中,host的值就是在docker-compose.yml里面指定的MySQL容器的名稱。

這是因為PHP代碼是在FPM容器中,FPM容器啟動時會自動在/etc/hosts中加上:

172.17.0.2 mysql 11e55f91c4c3 dlnmp_mysql_1

就是說,mysql自動指向了MySQL容器動態生成的IP。

9.2 使用Redis

Redis使用和MySQL類似。

在主機和容器內部都通過地址127.0.0.1,端口6379訪問。

PHP則是跨容器訪問,host參數用redislinks指定的名稱),端口用6379

10 讓DNMP隨系統啟動

到這里我們用docker搭建的Docker (Linux) + Nginx + MySQL + PHP環境已經可以正常使用了。

但每次啟動系統都得切換到項目目錄,再執行compose up,就略顯繁瑣。

要是能在系統啟動的時候自動啟動容器,豈不是更好,下面是具體的方法。

10.1 Ubuntu系統Unity桌面

從Launcher中搜索Startup Applications(啟動應用程序),

然后Add一項,名字:Dnmp,命令填:

docker-compose -f /home/gary/dnmp/docker-compose.yml up -d

其中,-f 指定docker-compose.yml文件的位置。

然后保存即可。

10.2 其他Linux系統

其他命令行下的Linux系統,可以直接編輯 /etc/rc.local 文件,加上上面的命令。

Docker相關的有用文章:

  1. Docker 常用命令
  2. docker-compose中ports和expose的區別
  3. 手動用Docker一步步部署LNMP完整教程
  4. Docker容器使用十大注意事項

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM