Laravel學習 - 在Docker下開發時遇到數據庫連接問題

公司的backend環境要求統一的docker下開發。之前只是零星地看過docker的東西,也沒覺得對當時的公司環境有什麼幫助就放棄了。現在仍然覺得放於小公司的開發和維護環境來看,docker並不是一個好選擇。

當然docker有其天然的優勢,譬如:

統一開發環境:所有人的運行環境是一致的,也避免了多種環境下每個人遇到的各種各樣的問題。

多種環境選擇:在不同的運行環境校驗代碼的兼容性,docker是一個非常棒的選擇。

部署環境擴容:docker的swarm模式可以方便快速地通過manager/worker的node增減實現運行容器的負載擴容。

但是,所有的優點都來自於成本:

一是docker的Dockerfile編寫維護成本,相當來說,這部分成本很小,甚至可以忽略不計。(官網有大把的資源可以使用)

二是docker的學習成本,每個人都會花出相當大的學習時間來了解docker的運行機制,掌握docker環境下開發的注意要點。

三是docker的機制對於小公司來說並不能負擔。雖然docker環境的開銷很小,但對於小公司而言,用戶量並沒有現下流行的大數據吹噓的那麼誇張,在單機或雙機下一般來說也不成爲問題。尤其是在阿里雲和亞馬遜這些公有云的負載均衡系統支持下,也可以實現一定程度的擴容。

其實最主要的就是:人和錢,最終都是因爲錢。


上面說了這麼多,其實都是總結,有點跑題了。

今天在學習Laravel的Lumen框架時,遇到了點小問題。

(2/2) QueryException
SQLSTATE[HY000] [2002] Connection refused (select ....)

(1/2) PDOException
SQLSTATE[HY000] [2002] Connection refused

剛看到這個錯誤時,第一反應是SQL出錯了,並沒有注意到提示Connection refused。

Lumen框架中有兩個配置的地方:

1/ .env文件(cp .env.example .env)

DB_HOST=127.0.0.1
DB_PORT=3306

2/ config/*.php (--database)

'connections' => [
    'driver' => 'mysql',
    'host'   => env('DB_HOST', '127.0.0.1'),
    'port'   => env('DB_PORT', 3306),
];

需要注意的是,docker環境下你只能是通過映射出來的端口對其進行連接。如:

c2c987bef6d7        mariadb:10.1.36     "docker-entrypoint.s…"   23 hours ago        Up 2 hours          0.0.0.0:3306->3306/tcp   hi-mysql

可以看到,0.0.0.0:3306->3306,表示外部的3306端口映射到內部的3306端口。所以我們可以通過127.0.0.1的3306端口連接到docker下的mariadb進行管理。

但是在Lumen下的配置也配置了127.0.0.1卻爲什麼會出現Connection confused呢?

原因在於,PHP的代碼同樣是運行在docker環境下,而不是實體機上。所以docker下php(service)的container下並沒有mysql服務。

解決方法:

1、查看mariadb所在的container的IP

docker inspect <container>|grep IPAddress
--
"IPAddress": "172.20.0.2"

2、修改.env中的配置

DB_HOST=172.20.0.2

再次刷新頁面,連接成功,OK!


問題又來了,通過修改IP是可以連接了。但是每次docker stop/start的時候,container的IP是會變化的……我們又怎麼辦呢?

在docker-compose.yml文件中,定義了不同的service,如:

version: '3'
services:
  db:
    image: mariadb:10.1.36
    container_name: hi-mysql
    volumes:
      - ./db_data:/var/lib/mysql
    ports:
      - 3306:3306

db就是service的name,通過這個name就可以達到與IPAddress同樣的連接預期結果。另外,container_name的名稱也可以用來作爲此作用。

// Same as Using IP
DB_HOST=db
// Same as db
DB_HOST=hi-mysql

It's really done now!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章