假設我們的 server 只有一台,PHP 環境為 docker container,而資料庫為實體機安裝,資料庫 3306 防火牆防堵不對外,但要允許從 Docker 環境內的服務存取,最簡單的方式就是防火牆讓 Docker 產生的 network interface 通過,下面我們來實做這件事。
今天示範環境為使用 Vagrant 起一台 Ubuntu jammy64,然後在裡面進行防火牆的測試。
sudo service ufw start
sudo ufw enable
sudo ufw allow ssh
記得開啟防火牆要先把 ssh 打開,不然就悲劇了,接著安裝 MySQL,docker 以及 docker compose 部分就麻煩自行安裝。
sudo apt install -y mariadb-server mariadb-client
安裝完畢後,我們來建立測試用資料庫以及帳號。
sudo mysql
create database laravel;
GRANT ALL PRIVILEGES ON `laravel`.* TO 'homestead'@'%' IDENTIFIED BY 'secret' WITH GRANT OPTION;
這邊權限開 % 沒關係,因為我們只會允許 docker network 指定的 network interface 進入而已。
docker-compose.yml
version: "3.9"
services:
fpm:
container_name: fpm
build: .
restart: always
working_dir: /www
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- front_end
volumes:
- ./www/:/www
networks:
front_end:
driver_opts:
com.docker.network.bridge.name: br-fpm
Dockerfile
FROM php:8.1-fpm
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
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 && \
install-php-extensions @composer pdo_mysql mbstring exif pcntl bcmath gd
WORKDIR /www
這是要安裝 Laravel 的最小環境,我們今天只是要測試連線所以其他的設定就先不理會了。
sudo docker compose up -d
等 image build 完以及 service 起來以後,我們來利用指令安裝一個 Laravel 的環境。
sudo docker compose exec fpm composer create-project laravel/laravel .
接著我們打開 .env 檔案設定資料庫連線內容。
DB_CONNECTION=mysql
DB_HOST=host.docker.internal
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=homestead
DB_PASSWORD=secret
這時來測試一下連線。
sudo docker compose exec fpm php artisan migrate
因為防火牆擋住了,所以 connection 會 hang 住,最終失敗,接著來開始防火牆設定。
sudo ufw allow in on br-fpm to any port 3306
接著再執行一次 migrate
的指令。
sudo docker compose exec fpm php artisan migrate
INFO Preparing database.
Creating migration table ............................................................................................................... 10ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table .................................................................................................... 9ms DONE
2014_10_12_100000_create_password_resets_table .......................................................................................... 2ms DONE
2019_08_19_000000_create_failed_jobs_table .............................................................................................. 3ms DONE
2019_12_14_000001_create_personal_access_tokens_table ................................................................................... 4ms DONE
可以看到 migration 順利成功了,如果發生 connection refuse 的錯誤的話,記得把 MySQL 的 bind-address
設定為 0.0.0.0
。
iptable 的話用下方的指令應可達到一樣的效果。
iptables -A INPUT -i br-fpm -p tcp --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP