1. 程式人生 > >docker-compose使用volume部署mysql時permission deny問題解決

docker-compose使用volume部署mysql時permission deny問題解決

問題
整體情況為使用docker做mysql的容器,然後結合其他服務一起通過docker-compose啟動,並且為了一次性建表和設定使用者許可權我又在mysql中封裝了setup.sh、schema.sql、privileges.sql這些自定義的指令碼,在Dockerfile構造時執行,到目前為止都是正常的。

但是由於每次down掉容器後,mysql的資料會丟失無法持久化,所以在docker-compose.yml中配置了volume引數,然後就產生了如下的報錯,包括除錯過程中的報錯。

首先列幾個可能的報錯,這些都和這個有關係。

問題一:mysqld: Can’t create/write to file ‘/var/lib/mysql/is_writable’ (Errcode: 13 - Permission denied)

問題二:’su’ command in Docker returns ‘must be run from terminal’

問題三:/usr/bin/mysqld_safe: 637: /usr/bin/mysqld_safe: cannot create /var/lib/mysql/c0ce8fdc06d0.err: Permission denied

以上幾個問題都是我在除錯過程中出現的報錯,採用過以下辦法解決:

1、在docker-compos.yml中新增

user:"1000:50"
1
2、保證volume配置對應的是/var/lib/mysql目錄,不能是/var/lib/mysql/data更深一層目錄

3、在Dockerfile中新增許可權指令chmod一類的,來修改檔案許可權

上述的方法均無效,在列出真正的解決方案之前,我把我重要的幾個配置檔案列出來

docker-compose.yml
plate-nginx:
build: ./nginx
container_name: plate-nginx
links:
- plate-client:plate-client
- plate-server:plate-server
ports:
- "80:80"
- "443:443"
- "7000:7000"
plate-client:
build: ./client
container_name: plate-client
volumes:
- "/home/picture:/app/client/app/upload"
ports:
- "3000:3000"
- "3001:3001"
plate-server:
build: ./server
container_name: plate-server
ports:
- "7001:7001"
plate-mysql:
build: ./mysql
container_name: plate-mysql
volumes:
- "/home/data:/var/lib/mysql"
ports:
- "3306:3306"
environment:
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: 123456
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
links:
- plate-mysql:plate-mysql
ports:
- "8888:80"
environment:
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: 123456
PMA_HOST: plate-mysql
PMA_PORT: 3306

mysql下的Dockerfile
FROM mysql:5.6

#設定免密登入
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes

#將所需檔案放到容器中
COPY setup.sh /mysql/setup.sh
COPY schema.sql /mysql/schema.sql
COPY privileges.sql /mysql/privileges.sql

#設定容器啟動時執行的命令
CMD ["sh", "/mysql/setup.sh"]

setup.sh
#!/bin/bash
set -e

#檢視mysql服務的狀態,方便除錯,這條語句可以刪除
echo `service mysql status`

echo '1.啟動mysql....'
#啟動mysql
service mysql start
sleep 3
echo `service mysql status`

echo '2.開始匯入資料....'
#匯入資料
mysql < /mysql/schema.sql
echo '3.匯入資料完畢....'

sleep 3
echo `service mysql status`

#重新設定mysql密碼
echo '4.開始修改密碼....'
mysql < /mysql/privileges.sql
echo '5.修改密碼完畢....'

#sleep 3
echo `service mysql status`
echo `mysql容器啟動完畢,且資料匯入成功`

tail -f /dev/null
解決方案
真正的問題所在其實就是在伺服器上的volume目錄/home/data和容器裡目錄/var/lib/mysql擁有者不一樣導致的,那麼如何檢視擁有者,需要使用如下幾條指令

檢視容器中/var/lib/mysql的所有者
docker run -ti --rm --entrypoint="/bin/bash" plate_plate-mysql -c "ls -la /var/lib/mysql"
可以從圖中看出來這個目錄的所有者是mysql使用者組

檢視伺服器中/home/data的所有者
ls -la /home/data

在systemd-bus-proxy這個位置原來是root,這裡由於被我修改了所以是這樣,也就是說,這兩個目錄的所有者不同導致的許可權問題,現在把他們的id統一就可以了,統一前要先查出來容器裡的mysql使用者組id,然後修改伺服器的/home/data下的使用者組id

查出來容器裡的mysql使用者組id
docker run -ti --rm --entrypoint="/bin/bash" plate_plate-mysql -c "cat /etc/group"

可以看到mysql使用者組的id為999

修改伺服器檔案使用者組id
chown -R 999 /home/data

修改後再去檢視就如上圖一樣,許可權變成了systemd-bus-proxy,至於為什麼沒變成mysql呢,因為999是docker容器裡面的許可權id,不是伺服器的,所以伺服器不識別也是自然的,之後再重啟,執行

docker-compose build && docker-compose up -d