如何使用docker搭建一個全家桶開發環境

奕鵬 發表於 2021-07-26

特別說明

最近在GitHub上發現一個不錯的PHP全家桶開發環境,是使用的docker搭建的。不過看更新動態,作者很少維護了。同時也加入了這個群,也發現使用這個倉庫的很多開發者會遇到很多的問題。為了讓這個倉庫發揮真正的作用,變fork了一個倉庫,保證後面的長時間更新和解決大家所遇到的問題。

Gitee倉庫地址:gitee.com/bruce_qiq/php_dnmp

GitHub倉庫地址:github.com/bruceqiq/php_dnmp

使用說明

如果你在使用的過程中發現什麼問題,可以提issue。如果你的問題比較著急,需要得到快速解決,你可以新增下面的公眾號,關注之後,點選相關資源選單,得到倉庫維護者的即使支援。

文件說明

DNMP(Docker + Nginx + MySQL + PHP7/5 + Redis)是一款全功能的LNMP一鍵安裝程式

使用前最好提前閱讀一遍目錄,以便快速上手,遇到問題也能及時排除。

DNMP專案特點:

  1. 100%開源
  2. 100%遵循Docker標準
  3. 支援多版本PHP共存,可任意切換(PHP5.4、PHP5.6、PHP7.1、PHP7.2、PHP7.3)
  4. 支援繫結任意多個域名
  5. 支援HTTPS和HTTP/2
  6. PHP原始碼、MySQL資料、配置檔案、日誌檔案都可在Host中直接修改檢視
  7. 內建完整PHP擴充套件安裝命令
  8. 預設支援pdo_mysqlmysqlimbstringgdcurlopcache等常用熱門擴充套件,根據環境靈活配置
  9. 可一鍵選配常用服務:
    • 多PHP版本:PHP5.4、PHP5.6、PHP7.1-7.3
    • Web服務:Nginx、Openresty
    • 資料庫:MySQL5、MySQL8、Redis、memcached、MongoDB、ElasticSearch
    • 訊息佇列:RabbitMQ
    • 輔助工具:Kibana、Logstash、phpMyAdmin、phpRedisAdmin、AdminMongo
  10. 實際專案中應用,確保100%可用
  11. 所有映象源於Docker官方倉庫,安全可靠
  12. 一次配置,Windows、Linux、MacOs皆可用
  13. 支援快速安裝擴充套件命令 install-php-extensions apcu

1.目錄結構

/
├── data                        資料庫資料目錄
│   ├── esdata                  ElasticSearch 資料目錄
│   ├── mongo                   MongoDB 資料目錄
│   ├── mysql                   MySQL8 資料目錄
│   └── mysql5                  MySQL5 資料目錄
├── services                    服務構建檔案和配置檔案目錄
│   ├── elasticsearch           ElasticSearch 配置檔案目錄
│   ├── mysql                   MySQL8 配置檔案目錄
│   ├── mysql5                  MySQL5 配置檔案目錄
│   ├── nginx                   Nginx 配置檔案目錄
│   ├── php                     PHP5.6 - PHP7.3 配置目錄
│   ├── php54                   PHP5.4 配置目錄
│   └── redis                   Redis 配置目錄
├── logs                        日誌目錄
├── docker-compose.sample.yml   Docker 服務配置示例檔案
├── env.smaple                  環境配置示例檔案
└── www                         PHP 程式碼目錄

2.快速使用

  1. 本地安裝
    • git
    • Docker(系統需為Linux,Windows 10 Build 15063+,或MacOS 10.12+,且必須要64位)
    • docker-compose 1.7.0+
  2. clone專案:
     $ git clone https://github.com/yeszao/dnmp.git
  3. 如果不是root使用者,還需將當前使用者加入docker使用者組:
     $ sudo gpasswd -a ${USER} docker
  4. 拷貝並命名配置檔案(Windows系統請用copy命令),啟動:
     $ cd dnmp                                           # 進入專案目錄
     $ cp env.sample .env                                # 複製環境變數檔案
     $ cp docker-compose.sample.yml docker-compose.yml   # 複製 docker-compose 配置檔案。預設啟動3個服務:
                                                         # Nginx、PHP7和MySQL8。要開啟更多其他服務,如Redis、
                                                         # PHP5.6PHP5.4、MongoDB,ElasticSearch等,請刪
                                                         # 除服務塊前的註釋
     $ docker-compose up                                 # 啟動
  5. 在瀏覽器中訪問:http://localhosthttps://localhost(自簽名HTTPS演示)就能看到效果,PHP程式碼在檔案./www/localhost/index.php

3.PHP和擴充套件

3.1 切換Nginx使用的PHP版本

首先,需要啟動其他版本的PHP,比如PHP5.4,那就先在docker-compose.yml檔案中刪除PHP5.4前面的註釋,再啟動PHP5.4容器。

PHP5.4啟動後,開啟Nginx 配置,修改fastcgi_pass的主機地址,由php改為php54,如下:

    fastcgi_pass   php:9000;

為:

    fastcgi_pass   php54:9000;

其中 phpphp54docker-compose.yml檔案中伺服器的名稱。

最後,重啟 Nginx 生效。

$ docker exec -it nginx nginx -s reload

這裡兩個nginx,第一個是容器名,第二個是容器中的nginx程式。

3.2 安裝PHP擴充套件

PHP的很多功能都是通過擴充套件實現,而安裝擴充套件是一個略費時間的過程,
所以,除PHP內建擴充套件外,在env.sample檔案中我們僅預設安裝少量擴充套件,
如果要安裝更多擴充套件,請開啟你的.env檔案修改如下的PHP配置,
增加需要的PHP擴充套件:

PHP_EXTENSIONS=pdo_mysql,opcache,redis       # PHP 要安裝的擴充套件列表,英文逗號隔開
PHP54_EXTENSIONS=opcache,redis                 # PHP 5.4要安裝的擴充套件列表,英文逗號隔開

然後重新build PHP映象。

docker-compose build php

可用的擴充套件請看同檔案的env.sample註釋塊說明。

3.3 快速安裝php擴充套件

1.進入容器:

docker exec -it php /bin/sh

install-php-extensions apcu 

2.支援快速安裝擴充套件列表

Extension PHP 5.5 PHP 5.6 PHP 7.0 PHP 7.1 PHP 7.2 PHP 7.3 PHP 7.4
amqp ✓ ✓ ✓ ✓ ✓ ✓ ✓
apcu ✓ ✓ ✓ ✓ ✓ ✓ ✓
apcu_bc ✓ ✓ ✓ ✓ ✓
bcmath ✓ ✓ ✓ ✓ ✓ ✓ ✓
bz2 ✓ ✓ ✓ ✓ ✓ ✓ ✓
calendar ✓ ✓ ✓ ✓ ✓ ✓ ✓
cmark ✓ ✓ ✓ ✓ ✓
dba ✓ ✓ ✓ ✓ ✓ ✓ ✓
decimal ✓ ✓ ✓ ✓ ✓
enchant ✓ ✓ ✓ ✓ ✓ ✓ ✓
exif ✓ ✓ ✓ ✓ ✓ ✓ ✓
ffi ✓
gd ✓ ✓ ✓ ✓ ✓ ✓ ✓
gettext ✓ ✓ ✓ ✓ ✓ ✓ ✓
gmagick ✓ ✓ ✓ ✓ ✓ ✓ ✓
gmp ✓ ✓ ✓ ✓ ✓ ✓ ✓
grpc ✓ ✓ ✓ ✓ ✓ ✓ ✓
http ✓ ✓ ✓ ✓ ✓ ✓ ✓
igbinary ✓ ✓ ✓ ✓ ✓ ✓ ✓
imagick ✓ ✓ ✓ ✓ ✓ ✓ ✓
imap ✓ ✓ ✓ ✓ ✓ ✓ ✓
interbase ✓ ✓ ✓ ✓ ✓ ✓
intl ✓ ✓ ✓ ✓ ✓ ✓ ✓
ldap ✓ ✓ ✓ ✓ ✓ ✓ ✓
mailparse ✓ ✓ ✓ ✓ ✓ ✓ ✓
mcrypt ✓ ✓ ✓ ✓ ✓ ✓ ✓
memcache ✓ ✓ ✓ ✓ ✓ ✓ ✓
memcached ✓ ✓ ✓ ✓ ✓ ✓ ✓
mongo ✓ ✓
mongodb ✓ ✓ ✓ ✓ ✓ ✓ ✓
msgpack ✓ ✓ ✓ ✓ ✓ ✓ ✓
mssql ✓ ✓
mysql ✓ ✓
mysqli ✓ ✓ ✓ ✓ ✓ ✓ ✓
oauth ✓ ✓ ✓ ✓ ✓ ✓ ✓
odbc ✓ ✓ ✓ ✓ ✓ ✓ ✓
opcache ✓ ✓ ✓ ✓ ✓ ✓ ✓
opencensus ✓ ✓ ✓ ✓ ✓
parallel* ✓ ✓ ✓ ✓
pcntl ✓ ✓ ✓ ✓ ✓ ✓ ✓
pcov ✓ ✓ ✓ ✓ ✓
pdo_dblib ✓ ✓ ✓ ✓ ✓ ✓ ✓
pdo_firebird ✓ ✓ ✓ ✓ ✓ ✓ ✓
pdo_mysql ✓ ✓ ✓ ✓ ✓ ✓ ✓
pdo_odbc ✓ ✓ ✓ ✓ ✓ ✓ ✓
pdo_pgsql ✓ ✓ ✓ ✓ ✓ ✓ ✓
pdo_sqlsrv ✓ ✓ ✓ ✓ ✓
pgsql ✓ ✓ ✓ ✓ ✓ ✓ ✓
propro ✓ ✓ ✓ ✓ ✓ ✓ ✓
protobuf ✓ ✓ ✓ ✓ ✓ ✓ ✓
pspell ✓ ✓ ✓ ✓ ✓ ✓ ✓
pthreads* ✓ ✓ ✓
raphf ✓ ✓ ✓ ✓ ✓ ✓ ✓
rdkafka ✓ ✓ ✓ ✓ ✓ ✓ ✓
recode ✓ ✓ ✓ ✓ ✓ ✓
redis ✓ ✓ ✓ ✓ ✓ ✓ ✓
shmop ✓ ✓ ✓ ✓ ✓ ✓ ✓
snmp ✓ ✓ ✓ ✓ ✓ ✓ ✓
snuffleupagus ✓ ✓ ✓ ✓ ✓
soap ✓ ✓ ✓ ✓ ✓ ✓ ✓
sockets ✓ ✓ ✓ ✓ ✓ ✓ ✓
solr ✓ ✓ ✓ ✓ ✓ ✓ ✓
sqlsrv ✓ ✓ ✓ ✓ ✓
ssh2 ✓ ✓ ✓ ✓ ✓ ✓ ✓
sybase_ct ✓ ✓
sysvmsg ✓ ✓ ✓ ✓ ✓ ✓ ✓
sysvsem ✓ ✓ ✓ ✓ ✓ ✓ ✓
sysvshm ✓ ✓ ✓ ✓ ✓ ✓ ✓
tdlib* ✓ ✓ ✓ ✓ ✓
tidy ✓ ✓ ✓ ✓ ✓ ✓ ✓
timezonedb ✓ ✓ ✓ ✓ ✓ ✓ ✓
uopz ✓ ✓ ✓ ✓ ✓ ✓ ✓
uuid ✓ ✓ ✓ ✓ ✓ ✓ ✓
wddx ✓ ✓ ✓ ✓ ✓ ✓
xdebug ✓ ✓ ✓ ✓ ✓ ✓ ✓
xhprof ✓ ✓ ✓ ✓ ✓ ✓ ✓
xmlrpc ✓ ✓ ✓ ✓ ✓ ✓ ✓
xsl ✓ ✓ ✓ ✓ ✓ ✓ ✓
yaml ✓ ✓ ✓ ✓ ✓ ✓ ✓
zip ✓ ✓ ✓ ✓ ✓ ✓ ✓
zookeeper ✓ ✓ ✓ ✓ ✓ ✓ ✓

此擴充套件來自github.com/mlocati/docker-php-exte...
參考示例檔案

3.4 Host中使用php命令列(php-cli)

  1. 參考bash.alias.sample示例檔案,將對應 php cli 函式拷貝到主機的 ~/.bashrc檔案。
  2. 讓檔案起效:
     source ~/.bashrc
  3. 然後就可以在主機中執行php命令了:
     ~ php -v
     PHP 7.2.13 (cli) (built: Dec 21 2018 02:22:47) ( NTS )
     Copyright (c) 1997-2018 The PHP Group
     Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
         with Zend OPcache v7.2.13, Copyright (c) 1999-2018, by Zend Technologies
         with Xdebug v2.6.1, Copyright (c) 2002-2018, by Derick Rethans

    3.5 使用composer

方法1:主機中使用composer命令

  1. 確定composer快取的路徑。比如,我的dnmp下載在~/dnmp目錄,那composer的快取路徑就是~/dnmp/data/composer

  2. 參考bash.alias.sample示例檔案,將對應 php composer 函式拷貝到主機的 ~/.bashrc檔案。

    這裡需要注意的是,示例檔案中的~/dnmp/data/composer目錄需是第一步確定的目錄。

  3. 讓檔案起效:

     source ~/.bashrc
  4. 在主機的任何目錄下就能用composer了:

     cd ~/dnmp/www/
     composer create-project yeszao/fastphp project --no-dev
  5. (可選)第一次使用 composer 會在 ~/dnmp/data/composer 目錄下生成一個config.json檔案,可以在這個檔案中指定國內倉庫,例如:

     {
         "config": {},
         "repositories": {
             "packagist": {
                 "type": "composer",
                 "url": "https://packagist.laravel-china.org"
             }
         }
     }
    

方法二:容器內使用composer命令

還有另外一種方式,就是進入容器,再執行composer命令,以PHP7容器為例:

docker exec -it php /bin/sh
cd /www/localhost
composer update

4.管理命令

4.1 伺服器啟動和構建命令

如需管理服務,請在命令後面加上伺服器名稱,例如:

$ docker-compose up                         # 建立並且啟動所有容器
$ docker-compose up -d                      # 建立並且後臺執行方式啟動所有容器
$ docker-compose up nginx php mysql         # 建立並且啟動nginx、php、mysql的多個容器
$ docker-compose up -d nginx php  mysql     # 建立並且已後臺執行的方式啟動nginx、php、mysql容器


$ docker-compose start php                  # 啟動服務
$ docker-compose stop php                   # 停止服務
$ docker-compose restart php                # 重啟服務
$ docker-compose build php                  # 構建或者重新構建服務

$ docker-compose rm php                     # 刪除並且停止php容器
$ docker-compose down                       # 停止並刪除容器,網路,影像和掛載卷

4.2 新增快捷命令

在開發的時候,我們可能經常使用docker exec -it進入到容器中,把常用的做成命令別名是個省事的方法。

首先,在主機中檢視可用的容器:

$ docker ps           # 檢視所有執行中的容器
$ docker ps -a        # 所有容器

輸出的NAMES那一列就是容器的名稱,如果使用預設配置,那麼名稱就是nginxphpphp56mysql等。

然後,開啟~/.bashrc或者~/.zshrc檔案,加上:

alias dnginx='docker exec -it nginx /bin/sh'
alias dphp='docker exec -it php /bin/sh'
alias dphp56='docker exec -it php56 /bin/sh'
alias dphp54='docker exec -it php54 /bin/sh'
alias dmysql='docker exec -it mysql /bin/bash'
alias dredis='docker exec -it redis /bin/sh'

下次進入容器就非常快捷了,如進入php容器:

$ dphp

4.3 檢視docker網路

ifconfig docker0

用於填寫extra_hosts容器訪問宿主機的hosts地址

5.使用Log

Log檔案生成的位置依賴於conf下各log配置的值。

5.1 Nginx日誌

Nginx日誌是我們用得最多的日誌,所以我們單獨放在根目錄log下。

log會目錄對映Nginx容器的/var/log/nginx目錄,所以在Nginx配置檔案中,需要輸出log的位置,我們需要配置到/var/log/nginx目錄,如:

error_log  /var/log/nginx/nginx.localhost.error.log  warn;

5.2 PHP-FPM日誌

大部分情況下,PHP-FPM的日誌都會輸出到Nginx的日誌中,所以不需要額外配置。

另外,建議直接在PHP中開啟錯誤日誌:

error_reporting(E_ALL);
ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');

如果確實需要,可按一下步驟開啟(在容器中)。

  1. 進入容器,建立日誌檔案並修改許可權:
     $ docker exec -it php /bin/sh
     $ mkdir /var/log/php
     $ cd /var/log/php
     $ touch php-fpm.error.log
     $ chmod a+w php-fpm.error.log
  2. 主機上開啟並修改PHP-FPM的配置檔案conf/php-fpm.conf,找到如下一行,刪除註釋,並改值為:
     php_admin_value[error_log] = /var/log/php/php-fpm.error.log
  3. 重啟PHP-FPM容器。

5.3 MySQL日誌

因為MySQL容器中的MySQL使用的是mysql使用者啟動,它無法自行在/var/log下的增加日誌檔案。所以,我們把MySQL的日誌放在與data一樣的目錄,即專案的mysql目錄下,對應容器中的/var/lib/mysql/目錄。

slow-query-log-file     = /var/lib/mysql/mysql.slow.log
log-error               = /var/lib/mysql/mysql.error.log

以上是mysql.conf中的日誌檔案的配置。

6.資料庫管理

本專案預設在docker-compose.yml中開啟了用於MySQL線上管理的phpMyAdmin,以及用於redis線上管理的phpRedisAdmin,可以根據需要修改或刪除。

6.1 phpMyAdmin

phpMyAdmin容器對映到主機的埠地址是:8080,所以主機上訪問phpMyAdmin的地址是:

http://localhost:8080

MySQL連線資訊:

  • host:(本專案的MySQL容器網路)
  • port:3306
  • username:(手動在phpmyadmin介面輸入)
  • password:(手動在phpmyadmin介面輸入)

6.2 phpRedisAdmin

phpRedisAdmin容器對映到主機的埠地址是:8081,所以主機上訪問phpMyAdmin的地址是:

http://localhost:8081

Redis連線資訊如下:

  • host: (本專案的Redis容器網路)
  • port: 6379

7.在正式環境中安全使用

要在正式環境中使用,請:

  1. 在php.ini中關閉XDebug除錯
  2. 增強MySQL資料庫訪問的安全策略
  3. 增強redis訪問的安全策略

8 常見問題

8.1 如何在PHP程式碼中使用curl?

參考這個issue:github.com/yeszao/dnmp/issues/91

8.2 Docker使用cron定時任務

Docker使用cron定時任務

8.3 Docker容器時間

容器時間在.env檔案中配置TZ變數,所有支援的時區請看時區列表·維基百科或者PHP所支援的時區列表·PHP官網

8.4 如何連線MySQL和Redis伺服器

這要分兩種情況,

第一種情況,在PHP程式碼中

// 連線MySQL
$dbh = new PDO('mysql:host=mysql;dbname=mysql', 'root', '123456');

// 連線Redis
$redis = new Redis();
$redis->connect('redis', 6379);

因為容器與容器是expose埠聯通的,而且在同一個networks下,所以連線的host引數直接用容器名稱,port引數就是容器內部的埠。更多請參考《docker-compose ports和expose的區別》

第二種情況,在主機中通過命令列或者Navicat等工具連線。主機要連線mysql和redis的話,要求容器必須經過ports把埠對映到主機了。以 mysql 為例,docker-compose.yml檔案中有這樣的ports配置:3306:3306,就是主機的3306和容器的3306埠形成了對映,所以我們可以這樣連線:

$ mysql -h127.0.0.1 -uroot -p123456 -P3306
$ redis-cli -h127.0.0.1

這裡host引數不能用localhost是因為它預設是通過sock檔案與mysql通訊,而容器與主機檔案系統已經隔離,所以需要通過TCP方式連線,所以需要指定IP。

8.5 容器內的php如何連線宿主機MySQL

1.宿主機執行ifconfig docker0得到inet就是要連線的ip地址

$ ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ...

2.執行宿主機Mysql命令列

 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
 mysql>flush privileges;
// 其中各字元的含義:
// *.* 對任意資料庫任意表有效
// "root" "123456" 是資料庫使用者名稱和密碼
// '%' 允許訪問資料庫的IP地址,%意思是任意IP,也可以指定IP
// flush privileges 重新整理許可權資訊

3.接著直接php容器使用172.0.17.1:3306連線即可

本作品採用《CC 協議》,轉載必須註明作者和本文連結
喜歡的,可以關注公眾號"卡二條的技術圈"。