docker搭建php開發環境
① Docker php 入門實踐(三)
在本教程的其餘部分,我們將基於 ThinkPHP 框架完成一個天氣查詢的應用。使用 天氣查詢-API文檔-開發指南-Web服務 API | 高德地圖API 的介面來實現我們的功能。把查詢數據緩存到 Mysql 中,這樣就不用每次頻繁的請求第三方的介面了(有請求次數限制)
選擇高德開放平台-天氣查詢 API 主要是因為它是免費的。當然你也可以使用其他的第三方天氣查詢介面,看個人喜好。
該應用是一個非常簡單的 REST API 應用,主要實現兩個介面。
在我們進行應用編碼之前,首先使用 Docker 安裝並運行 ThinkPHP
ThinkPHP 是一個免費開源的,快速、簡單的面向對象的 輕量級PHP開發框架 ,是為了敏捷WEB應用開發和簡化企業應用開發而誕生的。ThinkPHP從誕生以來一直秉承簡潔實用的設計原則,在保持出色的性能和至簡代碼的同時,更注重易用性。遵循 Apache2 開源許可協議發布,意味著你可以免費使用ThinkPHP,甚至允許把你基於ThinkPHP開發的應用開源或商業產品發布/銷售 。
這就是為什麼我選擇它作為本教程的教學框架。我不想讓你因為一個框架而放棄,但我也不想從頭開始建立所有的東西,因為該教程的重點是Docker,而不是我們的PHP應用。
用Docker 創建 ThinkPHP 應用 實際上比用本地配置PHP環境所需的操作少。並且為我們還需要使用 Composer,多虧了Docker,我們甚至不需要在主機上安裝它。
首先打開你的終端,創建一個項目目錄。
並進入到該目錄中
現在使用[官方Composer Docker鏡像](https://hub.docker.com/_/composer/)安裝 ThinkPHP 。
如果你查看weather-app/目錄,你會看到 ThinkPHP 6 的項目目錄,如下所示:
我們的 docker 運行命令與第二章中的命令相似,但我們使用了不同的鏡像。我們沒有使用運行hello.php 腳本的 PHP 鏡像,而是使用了一個 Composer 鏡像。讓我們來看看有什麼變化。
項目創建完成後,我們需要添加幾個路由 URL 和 Controller 文件 。讓我們打開 weather-app 目錄下的 app/controller , 然後新建 Weather.php 文件,內容如下:
然後打開 weather-app 目錄下的 app/route , 在 app.php 文件中追加如下內容:
現在我們可以在 Docker 容器中運行我們的應用程序,只是為了驗證我們的程序是否運行正常,因為我們只添加了兩個路由 URL。打開命令行,運行。
現在,在瀏覽器中打開 http://localhost:38000/weather-app/public/index.php/weather/1,你應該看到一個空頁面,上面有以下文字:
那麼恭喜你,你剛剛已經成功地在 Docker 中運行了你的第一個 ThinkPHP 應用程序。
這次我們使用的docker run命令與我們用來運行 hello.php 腳本 和composer create-project ...的兩個命令不同。原因是這次我們想獲得包含 Apache 的最新版本的PHP,這樣我們就可以為我們的 Web 應用提供服務。讓我們更詳細地了解新增的命令部分。
你可以通過向終端發送一個 "中斷 "信號來停止和退出終端。在 windows 上,這可以通過按 Ctrl 和按c來實現。
運行你的新網路應用程序的另一個選擇是在 "Detached"模式中運行容器。這意味著你在終端將不會看到來自你的容器的輸出。這可以通過在我們之前的命令中添加-d標志來實現。
在分離模式下啟動容器後,你的終端將顯示新容器的完整ID--類似於a70d25c2a7cedae673f8ab...如果你想停止這個容器,你可以使用docker stop命令,用容器的ID告訴Docker。比如說
因為輸入整個ID是很麻煩的,如果你願意,Docker允許你只輸入前三個或更多的字元。
最後,我建議為你的容器命名。我們在本書後面的許多例子中都會這樣做,因為用名字來記住一個容器比用隨機分配的ID要容易得多,再加上ID是隨機的,所以每次你運行一個新版本的容器時,它都會得到一個新的ID。只要不是已經有一個同名的容器,名字就可以多次發出來。為了給我們的新應用容器命名,我們可以用傳入的--name標志重新創建它。
在使用docker run命令時,還有許多可用的選項,所以你可能想更詳細地閱讀文檔。在我們開發其餘的應用程序時,我們會涉及其中的一些選項。
現在我們要引入高德的天氣 SDK ,在使用該 SDK 之前你需要閱讀高德開放平台-天氣查詢的技術文檔,再添加 SDK 之前我們首先要確保所有現有的容器都停止了。
這個命令將列出所有正在運行的容器。你也可以通過添加-a標志來查看停止的容器。
如果有任何容器正在運行,那麼在我們繼續前進之前,使用docker stop 來停止它們。
該命令將在你的項目中裝新的軟體包。在這個過程中,你應該在終端看到一些類似這樣的輸出。
現在 SDK 已經安裝完畢,可以使用了。
我們將使用剛剛添加的高德天氣 SDK 來完善我們的業務邏輯,打開 controller 目錄下的 Weather.php 添加以下內容:
我們做了一些更新--主要是對引入天氣 API 初始化天氣類
我們的應用程序已經初步完成了向API傳遞一個真實的位置ID並返回一些數據。首先,使用這個高德位置查詢找到一個位置ID。我使用的是上海的ID進行測試。310000,當然你直接傳 上海 也是可以的。ok,讓我們再次運行Docker容器。
並在你的瀏覽器中訪問正在運行的應用程序,地址是http://localhost:38000/weather-app/public/index.php/weather/310000。你應該可以看到一個JSON數據,看起來像這樣。
你的 Docker 化的 PHP 應用程序現在正從外部數據源返回真實數據,並在Apache中提供服務,但你可能會注意到,它的速度並不快(我的頁面載入時間為1.92秒!)。
高德天氣 API 是一個免費的服務,其他國家可能無法訪問。為了解決這個問題,我們將把查詢的數據保存在我們自己的 MySQL 資料庫中,可以再下次訪問的時候可以快速地響應。這將極大地提高性能,下個章節我們將學習如何用 Docker 將 MySql 與 PHP 應用程序相結合。
② Mac上通過docker配置PHP開發環境
本文將指導你在Mac上通過docker配置PHP開發環境,為PHP開發者提供參考。
首先,安裝Docker[1]。關於MAC上安裝,網上資源豐富,推薦使用阿里雲或Daocloud提供的加速器以提升效率。
接下來,使用docker-compose來管理開發環境。一個基本的PHP環境包括PHP-FPM、WEB伺服器(如Nginx)、MySQL資料庫,以及Redis或memcache等NoSQL服務。通過docker-compose.yml文件定義項目結構,包含單個或多個容器服務。
例如,MySQL服務配置:創建一個名為mysql的數據卷,指定版本(如mysql:5.7),設置環境變數如root密碼和資料庫信息,使用容器內的默認存儲路徑並映射主機埠。
在你的項目結構中,app目錄存放應用代碼,services下管理服務相關文件,包括自定義的Dockerfile。對於PHP服務,可能需要自定義鏡像,用Dockerfile定義軟體包和配置,如GD擴展的安裝和配置文件復制。
在構建過程中,可能會遇到軟體源問題,需替換為其他鏡像源。同時,php.ini和nginx配置文件也需要根據項目需求進行個性化設置。
最後,啟動並測試環境。創建index.php文件,運行docker-compose命令,通過瀏覽器訪問8000埠驗證PHP環境是否正常。資料庫管理工具如adminer.php也應能正常連接和使用。
總結,通過以上步驟,你已經成功配置了PHP開發環境。如需擴展到其他服務,可根據需要自行添加。如有進階學習需求,包括分布式架構、高並發等技術,可加入我的官方群獲取更多資源。
③ 如何 在Docker窗口中部署PHP開發環境
環境部署一直是一個很大的問題,無論是開發環境還是生產環境,但是 Docker
將開發環境和生產環境以輕量級方式打包,提供了一致的環境。極大的提升了開發部署一致性。當然,實際情況並沒有這么簡單,因為生產環境和開發環境的配置是完全不同的,比如日誌等的問題都需要單獨配置,但是至少比以前更加簡單方便了,這里以
PHP 開發作為例子講解 Docker 如何布置開發環境。
一般來說,一個 PHP 項目會需要以下工具:
Web 伺服器: Nginx/Tengine
Web 程序: PHP-FPM
資料庫: MySQL/PostgreSQL
緩存服務: Redis/Memcache
這是最簡單的架構方式,在 Docker 發展早期,Docker 被大量的濫用,比如,一個鏡像內啟動多服務,日誌收集依舊是按照 Syslog
或者別的老方式,鏡像容量非常龐大,基礎鏡像就能達到 80M,這和 Docker 當初提出的思想完全南轅北轍了,而 Alpine linux
發行版作為一個輕量級 Linux 環境,就非常適合作為 Docker 基礎鏡像,Docker 官方也推薦使用 Alpine 而不是 Debian
作為基礎鏡像,未來大量的現有官方鏡像也將會遷移到 Alpine 上。本文所有鏡像都將以 Alpine 作為基礎鏡像。
Nginx/Tengine
這部分筆者已經在另一篇文章 Docker 容器的 Nginx 實踐中講解了 Tengine 的 Docker 實踐,並且給出了
Dockerfile,由於比較偏好 Tengine,而且官方已經給出了 Nginx 的 alpine 鏡像,所以這里就用
Tengine。筆者已經將鏡像上傳到官方 DockerHub,可以通過
<code>docker pull chasontang/tengine:2.1.2_f</code>
獲取鏡像,具體請看 Dockerfile。
PHP-FPM
Docker 官方已經提供了 PHP 的 7.0.7-fpm-alpine 鏡像,Dockerfile 如下:
FROM alpine:3.4
# persistent / runtime deps
ENV PHPIZE_DEPS \
autoconf \
file \
g++ \
gcc \
libc-dev \
make \
pkgconf \
re2c
RUN apk add --no-cache --virtual .persistent-deps \
ca-certificates \
curl
# ensure www-data user exists
RUN set -x \
&& addgroup -g 82 -S www-data \
&& adser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# http://git.alpinelinux.org/cgit/aports/tree/main/apache2/apache2.pre-install?h=v3.3.2
# http://git.alpinelinux.org/cgit/aports/tree/main/lighttpd/lighttpd.pre-install?h=v3.3.2
# http://git.alpinelinux.org/cgit/aports/tree/main/nginx-initscripts/nginx-initscripts.pre-install?h=v3.3.2
ENV PHP_INI_DIR /usr/local/etc/php
RUN mkdir -p $PHP_INI_DIR/conf.d
##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data
##</autogenerated>##
ENV GPG_KEYS
ENV PHP_VERSION 7.0.7
ENV PHP_FILENAME php-7.0.7.tar.xz
ENV PHP_SHA256
RUN set -xe \
&& apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
curl-dev \
gnupg \
libedit-dev \
libxml2-dev \
openssl-dev \
sqlite-dev \
&& curl -fSL "http://php.net/get/$PHP_FILENAME/from/this/mirror" -o "$PHP_FILENAME" \
&& echo "$PHP_SHA256 *$PHP_FILENAME" | sha256sum -c - \
&& curl -fSL "http://php.net/get/$PHP_FILENAME.asc/from/this/mirror" -o "$PHP_FILENAME.asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& for key in $GPG_KEYS; do \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done \
&& gpg --batch --verify "$PHP_FILENAME.asc" "$PHP_FILENAME" \
&& rm -r "$GNUPGHOME" "$PHP_FILENAME.asc" \
&& mkdir -p /usr/src \
&& tar -Jxf "$PHP_FILENAME" -C /usr/src \
&& mv "/usr/src/php-$PHP_VERSION" /usr/src/php \
&& rm "$PHP_FILENAME" \
&& cd /usr/src/php \
&& ./configure \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
$PHP_EXTRA_CONFIGURE_ARGS \
--disable-cgi \
# --enable-mysqlnd is included here because it's harder to compile after the fact than extensions are (since it's a plugin for several extensions, not an extension in itself)
--enable-mysqlnd \
# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
--enable-mbstring \
--with-curl \
--with-libedit \
--with-openssl \
--with-zlib \
&& make -j"$(getconf _NPROCESSORS_ONLN)" \
&& make install \
&& { find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; } \
&& make clean \
&& runDeps="$( \
scanelf --needed --nobanner --recursive /usr/local \
| awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
| sort -u \
| xargs -r apk info --installed \
| sort -u \
)" \
&& apk add --no-cache --virtual .php-rundeps $runDeps \
&& apk del .build-deps
COPY docker-php-ext-* /usr/local/bin/
##<autogenerated>##
WORKDIR /var/www/html
RUN set -ex \
&& cd /usr/local/etc \
&& if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x don't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi \
&& { \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
} | tee php-fpm.d/docker.conf \
&& { \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = [::]:9000'; \
} | tee php-fpm.d/zz-docker.conf
EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##