2024-03-24

[Windows] docker desktop 4.26.0 開始會遇到 container 在啟動後維持了一定時間(大概30分鐘)時,外部host就無法對該容器進行操作

先說明,這有可能只是在下自己遇到的情況…

就是,某天在下 Windows 11 當時使用的 docker desktop 是在 4.25.0 然後更新到 4.26.0 時發生了一些奇怪的問題…

先說明在未更新前的環境

os: win11

cpu: amd ryzen 2700x

ram: 2 * 16G

app: docker desktop 4.25.0

containers: ubuntu 20.04 lts(內裝了 apache, php, mysql, phpmyadmin)

因為我大部份進行開發都是在公司上班時用工作機(筆電),當時工作機的 docker desktop 是更新到 4.25.2,家裡的桌機主要是為了在家工作時可以拿來開發,所以平時 docker desktop 我是不太會去更新

然後就有天看到有提醒有新版本 4.26.0 可以更新,我也沒想太多,就進行動作,然後更新完就把 docker desktop 關掉了,也沒去留意。

直到有天是公司 pm 告知客戶有反應前次更新有一些狀況,問我能不能先在家更新,更新完再來上班,我想說也行,就在30分鐘內完成了修正然後 hotfix 到客戶端去,正準備結束時就不知道為啥就按到了系統頁面的重新整理,結果發現一直在 loading…

2024-03-23

docker-compose 在 windows 環境該如何在 volumns 中設定掛載外部路徑

在 docker run 建立 container 的指令中,可以用 "-v {host-path}:{container-host-path}" 的方式來掛載主機路徑(host-path)至容器路徑(container-host-path)。

而主機路徑可以直接用絕對路徑的寫法,像 "-v D:\abc:/var/www/html"...

但,這方式在 docker-compose.yml 的 volumns 中這樣寫雖然不會報錯,但容器路徑 /var/www/html 卻會是空的,我假設 docker-compose.yml 中是這樣寫的(容器路徑我是假設的)
volumns:
  - "D:\abc:/var/www/html"
  - "./def:/var/www/html2"

"./def" 是以 docker-compose.yml 這個檔案的路徑開始中的 def 資料匣

我假定在 D:\abc 和 def 中都放了一個 index.html,在 container 啟動後,實際到 /var/www/html 路徑下查看,會發現是空的…而到 /var/www/html2 中查看則會有看到 index.html

在下試過很多寫法,但好像都無法掛載不是跟 docker-compose.yml 同路徑的其他路徑…但後來在 google 搜尋之後,發現了狀況,要掛載非 docker-compose.yml 同路徑的其他路徑,除了要寫絕對路徑的寫法外,寫法要改成

//{Disk drive}/path

例如: D:\abc 的掛載就要寫成

- "//d/abc:/var/www/html"

如此就能正常掛載到想要的外部路徑

註: 我自己後來把 docker desktop 在「用/不用 WSL」切換來切換去,有發現似乎「//d/abc」的這個方式是在「用 WSL」的情境下才有支援,「不用 WSL」的情境下還是要使用「D:\abc」的寫法,供大家參考

MySQL: ERROR...Aborted connection...to db: unconnected user:... host:... (init_connect command failed)... MySQL server has gone away!!

呃,沒錯,mysql 又遇坑了

不過遇上的前因是…我在把 apache, mysql, php-fpm, phpmyadmin 利用 docker 來運行在各自專屬的 container 上時,在 phpmyadmin 登入後所出現的訊息

因為這作法我沒有特別在 mysql 的 container 中去指定我自己優化的 mysql.cnf,而是改用 command 的命令加載去啟動的,所以我在 docker-compose.yml 中,mysql 的 command 的部份我有用到

command: [

...,

'--init_connect="SET NAMES utf8mb4"',

'--init_connect="SET collation_connection = utf8mb4_unicode_ci"'

]

然後 docker-compose up 的過程是沒什麼問題,當用 phpmyadmin 登入時就會看到頁面直接出現跟本篇標題差不多的文字,然後資料庫選單沒出現,重整網頁後也只是跳回登入,再次登比也是一樣。

這時我就直接進入 mysql container 內,直接用指令的方式登入

mysql -u {username} -p

剛登入是沒什麼異狀,但要求展示資料庫列表( show databases; )時就出現跟 phpmyadmin 登入時看到的異常訊息是一樣的( 註: 如果直接以高權限的帳戶登入,像 root 反而一切都很正常,沒有異常訊息 )

因為訊息中有提到 "init_connect command failed",所以先把 init_connect 的資料列出來看看

SHOW VARIABLES LIKE '%init_connect';

其結果為

| Variable_name |         Value       |
|-------------------------------------|
| init_connect  | 'SET NAMES utf8mb4' |

因為我有其他的 mysql 也有用到同樣的 init_connect 的命令,但是該命令是寫在 mysql.cnf 中,不是跟本次發生狀況的 mysql 一樣是用 docker 帶參數命令去生成的,所以我進到正常的 mysql 中看了一下,發現列出來的 init_connect 的值是不該帶有單引號的。

所以,我將 docker-compose.yml 中的 mysql 的 command 中有關於 init_connect 的命令改寫成

command: [

...,

'--init_connect=SET NAMES utf8mb4;SET collation_connection = utf8mb4_unicode_ci'

]
這樣 phpmyadmin 或 mysql 的登入就沒有再出現那個異常訊息了

2023-12-05

MySQL 沒有特別注意的 Collation 問題

這情況是一個我沒有特別發現,但是當出現錯誤時卻花了大把的時間 trace & debug 的事…

事由:

    我有兩個表,就叫 a 跟 b 好了

a {

  `id`: big integer, auto_increment, primary key,

  `sn`: varchar(50), utf8mb4_bin, unique key

}

b {

  `id`: big integer, auto_increment, primary key,

  `a_id`: big integer, foreign key references `a`.`id`,

  `sn`: varchar(50), utf8mb4_unicode_ci, unique key

}

我是後面接手維護的,我進行調整 a/b 表的 sn 的計算,利用 mysql trigger before insert 的時候去計算新的 sn,計算的操作是特別為了 a 跟 b 表各別寫一個 function 去做,就先叫 func_a 跟 func_b 好了

因為 b 跟 a 表的關係,所以 b.sn 的編碼格式中是有用到 a.sn 的,所以在 func_b 中,是要先以 NEW.`a_id` 到 a 表查 a.sn 後再回來用 a.sn 來串出 b.sn

2023-03-08

MySQL 遭遇奇怪的 VIEW ERROR 1356 view 'xxx' references invalid table(s) or column(s) or function(s) or definer/invoker...

 環境說明

  • windows server 2019
  • apache 2.4
  • mysql 8.0.28
  • Laravel 8, php 7.4
---
吃完晚餐後,突然接到老闆的 line call 說客戶系統那邊有關 mes 的功能頁面都會出現 server error 的 alarm 訊息,讓我去看看

查看 laravel.log 後發現反饋的訊息是如標題的
view 'xxx' references invalid table(s) or column(s) or function(s) or definer/invoker...

的訊息

看到就利用 CLI 連入 mysql engine 查看 user 權限,但利用 mysql information_schema 查權限,發現都沒有奇怪的地方。

該套系統除了客戶的環境有用,在公司的 aws 的環境上也有用,但沒有同樣的問題發生。

後來直接針對一頁所使用的 api 反查到相關 laravel 的 controller/model 中進行斷點檢查時發現,在經過特定的一行程式後才會出現該異常,在該行程式之前把結果列印出來是正常的…

該行程式主要是進行工單有強制停止屬性的就排除掉,但該系統有分總工單跟明細工單兩種模式,我當下把系統切到明細工單再來瀏覽,發現沒有異常…

而在總工單模式下,要過濾強制停止的工單的作法,是在總工單的 view 表中,有用 JSON_LENGTH() 去把總工單中有多少明細工單的數量獨立出來一個欄位,然後在查表時,先計算總工單中有強制停止屬性的明細工單的數量如果與總工單中明細數量相等的話,就代表該總工單要被過濾掉。

但問題就是發生在這個「比較」上, 假設我是這樣設計 view 表的(假設是叫 view_a)

SELECT JSON_LENGTH(`總工單中的明細工單資料集成`) AS `明細工單總數` FROM `總工單`;

以上存為 view 表

然後在工單查詢中是利用以下的查詢進行過濾

SELECT * FROM `view_a` WHERE JSON_LENGTH( IFNULL( JSON_EXTRACT(`總工單中的明細工單資料集成`, '$.*.強制停止'), '[]')) < `明細工單總數`;

這樣就會出現 1356 的 error

改成

SELECT * FROM `view_a` WHERE JSON_LENGTH( IFNULL( JSON_EXTRACT(`總工單中的明細工單資料集成`, '$.*.強制停止'), '[]')) <JSON_LENGTH(`總工單中的明細工單資料集成`);

就可以正常的執行下去

實在奇怪???