文章簡介
在上面一篇文章中,分享過如何搭建和使用dnmp,今天分享如何修改dnmp中PHP容器的埠映射功能,
問題歸納
在PHP容器中,安裝了一個swoole擴展,啟動了一個server,埠是9501,在安裝dnmp中,docker配置中將9501給暴露出來了,按理來說,啟動服務之后宿主機就可以正常訪問了,但是提示如下資訊,

然后嘗試去telnet埠號,卻發現是測驗不通,
? ert@192 ~ telnet 127.0.0.1 9501
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
問題排查
第一步,檢測PHP容器內的9501埠是否正常啟動,發現埠是正常啟動的,接下來,看看是不是映射問題,
/www # netstat -anp | grep 9501
tcp 0 0 0.0.0.0:9501 0.0.0.0:* LISTEN 69511/tools.Master
第二步,查看docker的PHP容器埠映射有哪些,
? ert@192 ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
68a39b4d38ff dnmp_php "docker-php-entrypoi…" 23 hours ago Up 23 hours 0.0.0.0:9000->9000/tcp, 9501/tcp php
ert@192 ~
發現埠暴露有9000和9501,但是發現9501和9000的卻不一樣,猜想可能是9501沒有給映射出來,接下來,查看docker-compose.yml的埠設定情況,查看到如下代碼:
php:
build:
context: ./services/php
args:
PHP_VERSION: php:${PHP_VERSION}-fpm-alpine
CONTAINER_PACKAGE_URL: ${CONTAINER_PACKAGE_URL}
PHP_EXTENSIONS: ${PHP_EXTENSIONS}
TZ: "$TZ"
container_name: php
expose:
- 9501
extra_hosts:
- "www.site1.com:172.17.0.1"
volumes:
- ${SOURCE_DIR}:/www/:rw
- ${PHP_PHP_CONF_FILE}:/usr/local/etc/php/php.ini:ro
- ${PHP_FPM_CONF_FILE}:/usr/local/etc/php-fpm.d/www.conf:rw
- ${PHP_LOG_DIR}:/var/log/php
- ${DATA_DIR}/composer:/tmp/composer
restart: always
cap_add:
- SYS_PTRACE
networks:
- default
發現expose設定了9501,于是便查看了一下docker的expose配置項說明,檔案如下:
EXPOSE 指令是宣告運行時容器提供服務埠,這只是一個宣告,在運行時并不會因為這個宣告應用就會開啟這個埠的服務,在 Dockerfile 中寫入這樣的宣告有兩個好處,
a.一個是幫助鏡像使用者理解這個鏡像服務的守護埠,以方便配置映射;
b.另一個用處則是在運行時使用隨機埠映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的埠,
要將 EXPOSE 和在運行時使用 -p <宿主埠>:<容器埠> 區分開來,-p,是映射宿主埠和容器埠,換句話說,就是將容器的對應埠服務公開給外界訪問,而 EXPOSE 僅僅是宣告容器打算使用什么埠而已,并不會自動在宿主進行埠映射,
總結: docker組態檔中的expose并不是真正的將宿主機的埠和PHP容器的埠做映射,
問題解決
通過上面的分析,發現是實際沒做映射,接下來,我們直接修改一下組態檔,重新安裝docker容器即可,
第一步:修改如下兩個組態檔,一個是.env檔案,一個是docker-compose.yml檔案,
// .env
# 這里就是需要做映射的埠,多配置即可避免后期需要使用,
PHP_HOST_PORT=9000
PHP_HYPERF1_PORT=9501
PHP_HYPERF2_PORT=9502
PHP_HYPERF3_PORT=9503
// docker-compose.yml
php:
build:
context: ./services/php
args:
PHP_VERSION: php:${PHP_VERSION}-fpm-alpine
CONTAINER_PACKAGE_URL: ${CONTAINER_PACKAGE_URL}
PHP_EXTENSIONS: ${PHP_EXTENSIONS}
TZ: "$TZ"
container_name: php
ports:
# 這里的${xxx}和.env檔案一一對應,
- "${PHP_HOST_PORT}:9000"
- "${PHP_HYPERF1_PORT}:9501"
- "${PHP_HYPERF2_PORT}:9502"
- "${PHP_HYPERF3_PORT}:9503"
extra_hosts:
- "www.site1.com:172.17.0.1"
volumes:
- ${SOURCE_DIR}:/www/:rw
- ${PHP_PHP_CONF_FILE}:/usr/local/etc/php/php.ini:ro
- ${PHP_FPM_CONF_FILE}:/usr/local/etc/php-fpm.d/www.conf:rw
- ${PHP_LOG_DIR}:/var/log/php
- ${DATA_DIR}/composer:/tmp/composer
restart: always
cap_add:
- SYS_PTRACE
networks:
- default
第二步:洗掉之前的PHP重啟埠
docker stop 68a39b4d38ff && docker rm 68a39b4d38ff
第三步:重新啟動PHP容器,
docker-compose up php
此時,就重新啟動了一個PHP容器了,并且容器的埠也做好映射了,
ert@192 ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
68a39b4d38ff dnmp_php "docker-php-entrypoi…" 23 hours ago Up 23 hours 0.0.0.0:9000->9000/tcp, 0.0.0.0:9501-9503->9501-9503/tcp php
測驗效果
此時,我們啟動PHP容器對應的9501埠服務,訪問,結果如下:

這說明我們的埠映射成功了,接下來,我們進入NGINX容器配置一個反向代理,直接通過域名訪問對應的埠,
upstream travelApi {
# 這里的php直接寫PHP容器的名稱即可,
發現協程127.0.0.1是不行的,因為訪問的是容器內部的埠,
如果不通過容器訪問,則直接宿主機的IP,但是IP可能會變動,則寫容器名比較合適,
server php:9501;
}
server {
listen 80;
server_name travel_api.com;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
proxy_pass http://travelApi;
}
}
將對應的域名寫入到宿主機的host檔案,進行訪問,效果如下:

說明我們的反向代理也配置成功了,
問題總結
1.docker中的expose不是做埠映射,而僅僅是宣告埠,
2.容器之間監聽埠,建議使用容器名稱,如NGINX中的反向代理配置,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/92634.html
標籤:其他
下一篇:玩轉dnmp之自定義PHP容器
