[Docker實踐系列-02]利用DockerCompose編排完整的PHP開發環境

Docker 重要性不用多作解釋,咱們每天吵着雲原生,最重要的一門技術,你是否掌握了呢?從今天,一塊兒來Docker吧!php

1. 目標

一、利用 docker-compose 編排一個PHP開發環境;
二、PHP 常見擴展安裝;
三、Nginx php-fpm Mysql Redis等容器互聯;
四、PHP 程序可以操做 Mysql Redis
二、蒐集相關日誌便於排查;html


2. 工具

一、操做系統:Ubuntu
二、編輯器:VSCode
三、Docker
四、Docker Compose 官方文檔
五、Compose 中文手冊
六、若是Docker鏡像拉取慢,能夠嘗試這個 www.daocloud.io/mirrormysql


3. 步驟

3.1 檢查軟件

確保 Docker 和 Docker Compose 已安裝好
好比linux

docker -v Docker version 19.03.1, build 74b1e89nginx

docker-compose -v docker-compose version 1.17.1, build 6d101fbgit

3.2 建立 docker-compose.yml 文件

在你的文件夾中新增這個文件,這是咱們編排的模板文件,格式以下github

version: '3'
services:
  php-workspace:
    image: php:7.3-fpm-alpine
  nginx:
    image: nginx:alpine
複製代碼

注意點:
一、模板中定義的 version 字段聲明瞭模板的格式和支持聲明字段,3 是目前比較推薦也用的比較多的的版本
二、注意 key 的層級和空格,咱們可使用命令 docker-compose config 命令檢查格式是否正確
三、使用 VSCode方便的一點是能夠看到能夠代碼能夠根據層級摺疊
redis

image.png

四、alpine是一種小型輕量的Linux,咱們使用基於 alpine 的鏡像是由於作出的鏡像體積比較小,關於後期容器構建的優化,這個是另一個話題,這裏不展開闡述。

3.3 「讓子彈飛起來」

docker-compose up --build 構建鏡像並啓動容器sql

這時能看到有兩個已經在運行的容器和鏡像
docker

image.png

3.4 讓 Nginx 工做起來

剛剛啓動的容器可使用 docker-compose down 來關閉項目,還會自動刪除容器。
如今,咱們要指定端口讓 Nginx 能處理請求,能夠參考 Compose 中文手冊的模板文件的語法。

image.png

3.4.1 增長 ports 參數

指定宿主機端口和容器端口的映射關係,以下;

version: '3'
services:
  php-workspace:
    image: php:7.3-fpm-alpine
  nginx:
    image: nginx:alpine
    ports:
      - "8080:8080"
複製代碼

3.4.2 執行 docker-compose up

去瀏覽器請求 localhost:8080

image.png

3.5 PHP文件交給 PHP-FPM 處理

image.png


其實選中容器右鍵能管理容器, Attach Shell 就能快速進入容器,咱們進入容器就能看到內部狀況,好比,nginx 的www目錄和配置目錄,php-fpm 的默認配置等等。

3.5.1 增長 nginx 的站點配置

新增文件 nginx/conf.d/site.conf文件,內容以下,下面的思路也能夠參考上篇《利用Docker搭建PHP開發環境》作法。

image.png

server {
    listen 8080;
    root /usr/share/nginx/html;
    index index.php index.html;
    server_name localhost;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    location ~ \.php$ {
        root /var/www/html; # 這裏指向的php容器的項目根目錄
        fastcgi_pass php-workspace:9000; #php-workspace是模板文件中的php-fpm服務名
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
複製代碼

3.5.2 修改 docker-compose.yml 文件

讓 nginx 和 php-fpm 服務基於Dockerfile 構建

version: '3'
services:
  php-workspace:
    build: ./php # 這裏php指咱們的建立的目錄
  nginx:
    build: ./nginx # 這裏nginx指咱們的建立的目錄
    ports:
      - "8080:8080"
複製代碼

3.5.3 新增 nginx/Dockerfile 文件

FROM nginx:alpine

COPY conf.d /etc/nginx/conf.d 複製代碼

3.5.4 新增 php/Dockerfile 文件

FROM php:7.3-fpm-alpine

複製代碼

3.5.5 增長code文件夾做爲php項目,新增index.php文件

<?php

phpinfo();

複製代碼

3.5.6 從新修改 docker-compose.yml 文件

讓項目文件夾以掛載的形式,讓php-fpm容器能夠直接讀取宿主機文件目錄,這樣咱們能夠很方便的修改代碼調試

version: '3'
services:
  php-workspace:
    build: ./php
    volumes: # 這裏指定數據卷,能夠指定多個, 中劃線表明值爲數組的一個成員
      - ./code:/var/www/html
  nginx:
    build: ./nginx #這裏nginx指咱們的建立的目錄
    ports:
      - "8080:8080"
複製代碼

3.5.7 走一下

重啓以前,再肯定下代碼文件大概位置

image.png

docker-compose up --build 從新啓動項目,咱們看到在前臺控制器的一些日誌

image.png


兩個容器都構建好了,php也啓動了。若是咱們如今請求 localhost:8080,還能看到nginx的請求日誌
image.png

3.6 鏈接Mysql

用法咱們依然參考了鏡像的介紹 >> hub.docker.com/_/mysql

3.6.1 添加 db 的服務

version: '3'
services:
  php-workspace:
    build: ./php
    volumes:
      - ./code:/var/www/html
  nginx:
    build: ./nginx
    ports:
      - "8080:8080"
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment: # 設定環境變量,只給定名稱的變量會自動獲取運行 Compose 主機上對應變量的值
      MYSQL_ROOT_PASSWORD: root
複製代碼

3.6.2 從新構建

docker-compose up --build

image.png


VSCode 容器管理中右鍵鏈接shell中進入容器執行 mysql -u root -p,確認密碼 root,肯定咱們的數據庫可用
image.png

3.6.3 安裝 pdo mysql

在操做以前咱們肯定下pdo是不支持mysql驅動的

image.png

修改 php 的 Dockerfile 文件以下
RUN 的第一條命令是修改了 alpine 系統的軟件源,方便後續安裝會更快點

FROM php:7.3-fpm-alpine

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \     && docker-php-ext-install pdo_mysql
複製代碼


從新構建項目 docker-compose up --build

image.png

3.6.4 修改 index.php 文件,代碼以下

<?php

$dsn = 'mysql:host=db;port=3306'; // host=db,這裏的db實際上是mysql的服務名
$user = 'root';
$password = 'root';

try {
    $dbh = new PDO($dsn, $user, $password);
    print_r($dbh);
} catch (PDOException $e) {
    echo 'Connection failed: '.$e->getMessage();
}

複製代碼

3.6.5 測試 Mysql

image.png

3.7 鏈接 Redis

3.7.1 容器安裝PHP擴展的兩種方式

在Docker Hub 中 php鏡像文檔中說的很清楚

  • 第一種是PHP核心的擴展能夠經過 docker-php-ext-install ext_name 安裝
  • 第二種是PECL
  • 第三種經過源碼包編譯

Redis的擴展,咱們用的是第二種。

3.7.2 修改 docker-compose.yml 文件,增長redis服務

version: '3'
services:
  php-workspace:
    build: ./php
    volumes:
      - ./code:/var/www/html
  nginx:
    build: ./nginx
    ports:
      - "8080:8080"
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
  redis:
    image: redis:5.0.5-alpine
複製代碼

3.7.3 從新構建

docker-compose up --build
構建後,咱們一樣能夠進入容器,使用 redis-cli 命令肯定redis是否可用

image.png

3.7.4 修改 php Dockerfile

由於pecl在alpine容器中安裝擴展會少一些東西,因此咱們先安裝了一個phpize_deps,用後刪除便可,保持鏡像瘦小

FROM php:7.3-fpm-alpine

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \     && docker-php-ext-install pdo_mysql \
    && apk add ${PHPIZE_DEPS} \ && pecl install redis-4.0.1 \ && docker-php-ext-enable redis \ && apk del ${PHPIZE_DEPS} 
複製代碼

從新構建,咱們修改index.php 代碼 phpinfo();能看到 redis擴展已打開

image.png

3.7.5 鏈接 Redis

修改 index.php 文件內容以下測試

<?php

$redis = new Redis();
$redis->pconnect('redis', 6379);

$key = 'first';
$redis->incr($key);

echo '頁面瀏覽了:'.$redis->get($key); die;
複製代碼


image.png

3.8 日誌蒐集

咱們回顧一下 nginx/conf.d/site.conf 的配置

server {
    listen 8080;
    root /usr/share/nginx/html;
    index index.php index.html;
    server_name localhost;
    # 咱們已經把nginx相關日誌寫到這裏了,如何放到宿主機呢?
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    # ... more something
}
複製代碼


docker日誌採集當然有不少方案,可是暫時不考慮集羣管理工具的日誌蒐集方案,這裏以數據掛載的形式,把 nginx 請求日誌落地到宿主機。

3.8.1 修改 docker-compose.yml 文件以下

version: '3'
services:
  php-workspace:
    build: ./php
    volumes:
      - ./code:/var/www/html
  nginx:
    build: ./nginx
    volumes: # 新增這兩行
      - ./log/nginx:/var/log/nginx/
    ports:
      - "8080:8080"
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
  redis:
    image: redis:5.0.5-alpine
複製代碼

3.8.2 重啓項目

docker-compose up 執行後,就能夠看到咱們的文件夾多了兩個目錄,還有兩個文件

image.png

3.9 優化

depends_on

能夠指定依賴項,解決容器啓動前後問題,好比一個應用若是依賴數據庫,要讓數據庫容器先啓動能夠設置

depends_on:
      - db
      - redis
複製代碼

環境變量

固然其實還有其餘不少有用的參數設置,好比感敏數據讀取,環境變量,配置host等等,後續均可以在開發中嘗試使用。


4. 總結

以上思路能夠解決本地開發中的不少問題了,若是項目中有使用 memcached 或者其餘應用,作法均可以參考Docker Hub中的鏡像文檔說明中引入。
除此以外,在Laravel 開發中以前早就有一個開源項目叫作 Laradock 來搭建Docker化的PHP應用,不只如此,還有不少中間件均可以利用 docker-compose 啓動,能夠參看 >> laradock.io/ ,可是裏邊有不少不少東西,由於要知足大部分人的擴展性,加了不少環境變量,if else 判斷,讓本來的 Dockerfile 更爲複雜,增長了不少邏輯。可是思路基本上是相同的。
另外還有幾點要點出:
一、docker-compose.yml 定義的一個項目會以所在的文件夾名爲項目名。
二、一個項目有一個默認網絡,項目中的服務彼此能夠互通,因此咱們剛剛在 site.conf 轉發php請求能夠直接用 php-workspace:9000 服務名來轉發,鏈接 數據庫也是能夠用 db  redis 等他們的服務名來鏈接。

image.png


5. 完整代碼

github.com/baiyutang/d…


6. 遺留問題

一、指定數據庫掛載的數據卷,好比Mysql,咱們能夠把其餘環境的數據庫直接以文件的形式拷貝,而後直接利用。這樣比咱們手動導入sql會更快遷移數據。

二、Mysql 鏡像如何瘦身,如今Mysql鏡像文件最大,如圖有445M

image.png


7. 下篇預告

其實PHP的Docker環境已經有一個開源項目 Laradock,使用方便 易於擴展,可是最大的問題是 感受臃腫 有時候安裝特別慢,特別是要考慮太多擴展插件等等製做出來鏡像特別大。因此下一篇的思路可能會圍繞如何優化今天作的這個 demo-docker-compose,或者作 Laradock 本地化工做?
其餘兩個思路:
一、直接進入到 k8s 課題
二、Docker化後如何作CI/CD


8. 擴展

相關文章
相關標籤/搜索