iT邦幫忙

0

iptables ip/port跳轉導向設定問題

舜~ 2021-02-28 13:25:232160 瀏覽

大家好

host環境:win10 pro 64bit
Docker Desktop 設定: Linux容器
PHP容器的OS:
Debian GNU/Linux 10 \n \l
Linux version 5.4.72-microsoft-standard-WSL2 (oe-user@oe-host) (gcc version 8.2.0 (GCC)) #1 SMP Wed Oct 28 23:40:43 UTC 2020

我在使用Docker架設PHP開發環境遇到一個問題
專案中很多資料庫連線是用 localhost 字串來連線
但php與mysql不在同一個容器中,
所以使用上必須要指定mysql容器的ip

但我不可能為此去修改我專案的資料庫連線IP
所以我有個想法,
把所有 127.0.0.1:3306 全部導去mysql容器的3306 port
所以我加上了
iptables -t nat -A PREROUTING --dst 127.0.0.1 -p tcp --dport 3306 -j DNAT --to-destination mysql8 3306
(mysql8是容器名稱,不知道這樣用對不對,但改用IP也是一樣,見下方php的dockerfile)
但安裝過程會出現

iptables v1.8.2 (nf_tables): unknown option "--dport"

Try `iptables -h' or 'iptables --help' for more information.

ERROR: Service 'php74' failed to build : The command '/bin/sh -c iptables -t nat -A PREROUTING --dst 127.0.0.1 -p tcp --dport 3306 -j DNAT --to-destination mysql8 3306' returned a non-zero code: 2

我在--dport--dport前面明明有-p tcp呀!!??

有人知道發生什麼事嗎?
或是有什麼方法可以替代iptables ??

上設定檔
docker-compose.yml

version: '3'
#   port表對應
#       9010 : xdebug
#       9011 : php 7.4 http
#       9012 : php 7.4 https
#       9013 : mysql 8.0
networks:
    mynet:
        #external: true #先前已建立,不重複建立
services:
    mysql8:
        container_name: mysql8
        image: mysql:8.0.23
        environment:
            MYSQL_ROOT_PASSWORD: turrteled
            MYSQL_ROOT_HOST: '%'
        networks:
            - mynet
        ports:
            - 9013:3306
        volumes:
            - ./mysql8/data:/var/lib/mysql
            - ./mysql8/log:/var/log/mysql
        command: mysqld --default-authentication-plugin=mysql_native_password --sql_mode=""
    php74:
        container_name: php74
        build: ./php74
        #image: php:7.4-fpm
        volumes:
            - ./www:/var/www/html
            - ./php74/conf.d:/usr/local/etc/php/conf.d
        depends_on:
            - mysql8
        networks:
            - mynet
        ports:
            - 9010:9000
    nginx118:
        container_name: nginx118
        image: nginx:1.18
        ports:
            - 9011:80
            - 9012:443
        volumes:
            - ./www:/var/www/html
            - ./nginx/log:/var/log/nginx
            - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - php74
        environment:
            WORKDIR: /var/www/html
        networks:
            - mynet

php的dockerfile

FROM php:7.4-fpm

RUN apt-get update 

# === 資料庫 ===
RUN docker-php-ext-install mysqli pdo pdo_mysql

# 加了會多一個warning: mysqli (mysqli) is already loaded!,
# 但不加,mysqli的設定就不會出現在php.ini中導致無法使用 @@
# 若有人知道原因請告知
# 好困擾...為什麼相同環境我電腦跑出來的總跟別人不一樣......
RUN docker-php-ext-enable mysqli

# === xdebug ===
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug


# localhost:3306要跳轉到mysql的IP
RUN apt-get install -y sudo vim iptables
RUN iptables -t nat -A PREROUTING --dst 127.0.0.1 -p tcp --dport 3306 -j DNAT --to-destination mysql8 3306
RUN service iptables save # 避免重開設定就消失

https://unix.stackexchange.com/questions/459206/list-ip-tables-in-docker-container
https://stackoverflow.com/questions/58377469/difference-between-cap-add-net-admin-and-add-capabilities-in-yml

目前想到的只有在php容器上直接apt安裝mysql來解決此問題~~
有其他解法嗎?

看更多先前的討論...收起先前的討論...
obarisk iT邦研究生 2 級 ‧ 2021-03-01 17:18:36 檢舉
ssh port forwarding
舜~ iT邦高手 1 級 ‧ 2021-03-02 18:06:44 檢舉
obarisk大大,能說明多一點嗎? 這能實現在php容器中的127.0.0.1:3306 tcp跳去mysql容器的3306 ?
我自己在試的時候
$mysqli = new mysqli("mysql8", "root", "turrteled");
就可以連上mysql,不需要特別轉port。
你可能沒有注意到mysql服務啟動的時間有點長,像我就跑了快5分鐘才可以正常使用。
docker logs mysql8
讀取mysql8的log 確定mysql啟動完畢
舜~ iT邦高手 1 級 ‧ 2021-03-04 11:18:14 檢舉
跑了快5分鐘才可以正常使用...這我真沒留意到....
另外因為我接手的專案多個地方使用localhost,
有沒有可能再php容器中讓localhost:3306自動導去mysql8 ??
我那個寫法就可以了
你再試試看 把host改成 {db container name} 應該是可以連上
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
JamesDoge
iT邦高手 1 級 ‧ 2023-02-21 09:53:41

根據你的錯誤訊息 "unknown option '--dport'",這表明你的 iptables 版本不支持 --dport 選項。這是因為 Docker 默認在創建容器時限制了容器的系統調用權限,這些權限不足以允許容器內的進程使用某些 iptables 選項。

要解決這個問題,可以在 Docker Compose 文件中為容器增加 privileged: true 選項,以獲得完全的系統特權,或者使用 Docker 的 --cap-add 選項授予容器訪問這些權限。

php74:
    container_name: php74
    build: ./php74
    privileged: true
    ...

在 Docker Compose 文件中使用 privileged: true 是一種簡單且快速的解決方案。但是,這也會使容器變得不安全,因為容器可以訪問主機上的所有設備和文件系統。如果你有更安全的解決方案,最好使用更細粒度的安全選項來授予容器所需的權限。

我要發表回答

立即登入回答