基于Docker統(tǒng)一PHP開發(fā)環(huán)境

背景

  • 團隊內每個開發(fā)人員PHP版本不一致
  • 本地開發(fā)環(huán)境與生產環(huán)境不一致摊滔,環(huán)境不一致易導致生產問題
  • 每次新人過來安裝PHP環(huán)境耗時比較長且不可控

目標

  • 所有開發(fā)人員環(huán)境保持一致
  • 開發(fā)環(huán)境與生產環(huán)境保持一致
  • 能快速安裝輕量級的開發(fā)環(huán)境

思路

  • 將標準PHP環(huán)境打包靜docker鏡像中砚蓬,所有開發(fā)成員代碼運行在容器里面褪那,本地不需要安裝開發(fā)環(huán)境(除IDE工具外)
  • 容器里面提供sshd服務,使開發(fā)者能夠通過ssh登陸并傳輸文件(類似輕量級虛擬機倔既,在容器啟動后利用sftp遠程同步文件比較有用)

構造環(huán)境鏡像

  • 版本
    linux:alpine3.13
    PHP: 7.4
  • 準備文件(在后面國建鏡像有用)

nginx主配置文件:nginx.conf

user                nginx;
worker_processes    auto;
error_log           /var/log/nginx/error.log notice;
pid                 /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    sendfile            on;
    keepalive_timeout   65;
    gzip                on;
    #tcp_nopush         on;
    log_format          main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    access_log          /var/log/nginx/access.log  main; 

    include /etc/nginx/conf.d/*.conf;
}

鏡像入口文件(用于啟動鏡像服務): entrypoint.sh

#!/bin/sh

/usr/sbin/sshd -D &
nginx &
php-fpm
  • 鏡像Dockerfile
    在有了上面兩個文件后牛曹,我們就可以開始構建我們的環(huán)境鏡像了
# 采用基于alpine的php-fpm鏡像(alpine為一個輕量級的linux鏡像)
FROM amd64/php:7.4-fpm-alpine3.13

# 復制PHP配置文件
RUN cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# 由于倉庫鏡像網絡問題谴轮,換成阿里云資源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

# 安裝php擴展(可以根據自己的需要安裝所需PHP擴展)
# install-php-extensions使用文檔:
# https://github.com/mlocati/docker-php-extension-installer
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions
RUN install-php-extensions swoole
RUN install-php-extensions mongodb
RUN install-php-extensions redis
RUN install-php-extensions rdkafka
RUN install-php-extensions bcmath
RUN install-php-extensions pdo_mysql

# 安裝composer
RUN php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" 
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer

# alpine利用apk進行系統(tǒng)包管理
# 更新apk庫并安裝時區(qū)數據庫、sshd服務识窿、nginx
RUN apk update && apk add tzdata openssh nginx

# 配置時區(qū)(alpine默認時區(qū)為0時區(qū)斩郎,與北京時間相差8小時,需要調整為Asia/Shanghai)
ENV TIME_ZONE=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone


# 安裝openssh喻频,容器啟動后可以通過ssh登陸或傳輸文件
# 初始賬號密碼為root:123456
RUN sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config &&\
    ssh-keygen -t dsa -P "" -f /etc/ssh/ssh_host_dsa_key &&\
    ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key &&\
    ssh-keygen -t ecdsa -P "" -f /etc/ssh/ssh_host_ecdsa_key &&\
    ssh-keygen -t ed25519 -P "" -f /etc/ssh/ssh_host_ed25519_key &&\
    echo "root:123456" | chpasswd


# 配置nginx主配置文件
COPY nginx.conf /etc/nginx/nginx.conf
COPY entrypoint.sh /data/entrypoint.sh

# 安裝swoft開發(fā)工具(swoft框架的開發(fā)工具缩宜,如果沒有用到則不需要安裝)
RUN wget https://github.com/swoft-cloud/swoft-cli/releases/download/v0.2.1/swoftcli.phar &&\
        mv swoftcli.phar /usr/local/bin/swoftcli &&\
        chmod a+x /usr/local/bin/swoftcli


# 設置默認工作目錄
WORKDIR /data/web/

# 暴露端口
EXPOSE 22
EXPOSE 80
EXPOSE 9000

# 啟動sshd、nginx半抱、fpm
CMD ["sh","/data/entrypoint.sh"]

構建鏡像

docker build -t jeanslin/php7.4-dev . 

查看構建后的鏡像


image.png

運行環(huán)境

  • 啟動容器
    此處可以將存放代碼的目錄掛載到容器里面脓恕,這樣宿主機和容器的代碼就是相同的
docker run -d 
    -p 10080:80 -p 10022:22 -p 19000:9000 
    -v /Users/it/project:/data/web/project
    jeanslin/php7.4-dev
  • 利用ssh登陸容器
    由于我們把容器的22端口映射到宿主機的10022端口,通過10022端口就可以登陸容器里面


    image.png

查看已啟動的服務進程窿侈,可以看到已啟動了php-fpm炼幔、nginx、sshd服務


image.png
  • 配置后端nginx文件:api.conf
    由于容器只對外開放了80端口史简,為了區(qū)分不同的服務乃秀,我們可以在宿主機/etc/hosts文件配置開發(fā)域名來映射到容器的不同服務肛著,此處將api.dev.com映射到127.0.0.1
server {
        listen       80;                                       
        server_name  api.dev.com;
        root         /data/web/;

        location / {
            index index.php index.html index.htm;
            try_files $uri $uri/ /index.php$is_args$args;
        }
        
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param SERVER_NAME $http_host;
            fastcgi_ignore_client_abort on;
        }
}

我們在容器的/data/web/寫一個phpinfo.php的腳本文件,用來調試服務是否正常

<?php
phpinfo();

由于容器的80端口是掛載到宿主機的10080端口跺讯,我們通過該端口訪問服務
訪問地址為:http://api.dev.com:10080/phpinfo.php

image.png

  • 配置前端nginx文件:web.conf
    在宿主機/etc/hosts文件將web.dev.com映射到127.0.0.1
    此處為了解決前端跨域問題枢贿,將/api/開頭的路徑轉發(fā)到api.dev.com
server {
        listen       80;
        server_name  web.dev.com;
        root         /data/web/;

        location / {
            index index.php index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        location ^~/api/ {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP        $remote_addr;
            proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy    true;
            proxy_pass http://@back/;
        }
}

upstream @back{
        server api.dev.com;
}

我們在容器/data/web/目錄創(chuàng)建一個index.html文件,內容如下

<html>
    <body>
        nice to meet you!
    </body>
</html>

由于容器的80端口是掛載到宿主機的10080端口刀脏,我們通過該端口訪問服務
訪問地址為:http://web.dev.com:10080/index.html

image.png

至此局荚,開發(fā)者本地nginx+php-fpm的開發(fā)環(huán)境已經準備完成,開發(fā)者通過拉取該鏡像使用即可(開發(fā)者本地需要安裝docker)愈污,本地無需安裝任何環(huán)境軟件耀态。

遠程開發(fā)

除上面的場景外,還可以用于以下場景

  • 我們還可以在一臺開發(fā)機上為每個開發(fā)者創(chuàng)建一個容器暂雹,然后開發(fā)者可以通過ssh服務遠程登錄到容器里面首装,這樣開發(fā)者本地docker也不需要安裝

  • 在一些swoole框架,比如swoft需要讀取文件注解的杭跪,如果通過掛載的方式把代碼掛到容器里面仙逻,在代碼變更熱重啟時會很慢,影響開發(fā)體驗涧尿,這時可以通過ssh自帶sftp服務直接將代碼直接同步到容器里面系奉,這樣容器熱重啟會快許多

以下我們基于swoft框架,用phpstorm演示一下如何遠程開發(fā)容器里面的代碼:
入口為:tools > Deployment > Configuration

配置connection姑廉,此處容器的22端口掛載到宿主機的10022端口喜最,我們通過宿主機的10022連接容器


image.png

我們添加一個Mappings,將本地的文件/Users/linjunda/it/tme/doc/doc_service同步到容器的/data/web/

image.png

tools > Deployment > Automatic upload 選擇為always庄蹋,該選項表示如果目錄代碼發(fā)生變更則自動同步到遠程服務器

我們先執(zhí)行一次全量的同步瞬内,入口為:tools > Deployment > Sync with deployed to


image.png

控制臺顯示文件同步完成信息


image.png

現(xiàn)在我們可以在容器里面啟動這個swoft服務的熱重啟監(jiān)聽


image.png

此處容器里面doc_service服務的監(jiān)聽為1007,我們通過nginx配置進行端口轉發(fā)

server {
        listen       80;
        server_name  doc.dev.com;
        root         /data/web/;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP        $remote_addr;
            proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy    true;
            proxy_pass http://@docBack/;
        }
}

upstream @docBack{
        server localhost:1007;
}

我們寫一個TestController

/**
 * @Controller(prefix="test")
 */
class TestController
{
    /**
     * @RequestMapping(route="test")
     */
    public function test(Response $response)
    {
        return $response->withContent("hello world");
    }
}

此處我們將doc.dev.com域名的所有請求轉發(fā)到1007端口下面限书,通過宿主機訪問如下


image.png

現(xiàn)在我們再IDE修改腳本文件后就會遠程同步到容器里面虫蝶,容器里面的swoft熱重啟服務監(jiān)聽到文件變化時會觸發(fā)服務重啟,這樣我們就相當于遠程在調試容器里面的代碼了倦西。

接下來我們在本地IDE把返回內容改為“nice to meet you!”能真,再訪問原來的地址,內容如下:


image.png

以上就是本次的一些分享扰柠,如果轉載請標明遠處粉铐,覺得對你有幫助的話,請點個贊吧 _

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末卤档,一起剝皮案震驚了整個濱河市蝙泼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劝枣,老刑警劉巖汤踏,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件织鲸,死亡現(xiàn)場離奇詭異,居然都是意外死亡溪胶,警方通過查閱死者的電腦和手機搂擦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哗脖,“玉大人瀑踢,你說我怎么就攤上這事〔疟埽” “怎么了丘损?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長工扎。 經常有香客問我,道長衔蹲,這世上最難降的妖魔是什么肢娘? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮舆驶,結果婚禮上橱健,老公的妹妹穿的比我還像新娘。我一直安慰自己沙廉,他們只是感情好拘荡,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撬陵,像睡著了一般珊皿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巨税,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天蟋定,我揣著相機與錄音,去河邊找鬼草添。 笑死驶兜,一個胖子當著我的面吹牛,可吹牛的內容都是我干的远寸。 我是一名探鬼主播抄淑,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驰后!你這毒婦竟也來了肆资?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤灶芝,失蹤者是張志新(化名)和其女友劉穎迅耘,沒想到半個月后贱枣,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡颤专,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年纽哥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栖秕。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡春塌,死狀恐怖,靈堂內的尸體忽然破棺而出簇捍,到底是詐尸還是另有隱情只壳,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布暑塑,位于F島的核電站吼句,受9級特大地震影響,放射性物質發(fā)生泄漏事格。R本人自食惡果不足惜惕艳,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驹愚。 院中可真熱鬧远搪,春花似錦、人聲如沸逢捺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽劫瞳。三九已至倘潜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間志于,已是汗流浹背窍荧。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留恨憎,地道東北人蕊退。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像憔恳,于是被迫代替她去往敵國和親瓤荔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內容