結果から
コンテナ側の実行ユーザーがrootである場合、読み書きとも制限なく行える。
コンテナ側の実行ユーザーが非rootである場合、ホスト側で DBファイルとそのディレクトリのパーミッションを緩めるか、DBファイルの所有者をコンテナ側の実行ユーザー に合わせなければ書き込みは行えない。(行えない場合に attempt to write a readonly database
エラーが出る)
以下、確認方法。
準備 あらかじめデータの入った SQLite データベースファイルを用意し、特定のディレクトリ (=コンテナにマウントするディレクトリ) に入れておく。
以下コマンドでディレクトリ作成 -> データベースファイルを作成&開き、初期データ投入。
mkdir data
sqlite3 ./data/db.sqlite
初期データ CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL
);
INSERT INTO users (name, email) VALUES ('キリウ君', 'kiriu-kun@example.com');
完了したら対話型インターフェースを .exit
で抜ける。
root ユーザーの場合 以下の Dockerfile
を作成する。これはコマンドラインから sqlite3
を使えて、かつ落ちずに起動し続けるだけのコンテナ。
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y sqlite3
CMD ["tail", "-f", "/dev/null"]
この Dockerfile
があるディレクトリで、以下コマンドでコンテナイメージをビルド。
docker build -t sqlite-with-root .
そして、ホスト側のDBファイルがあるディレクトリ ./data
をコンテナ側にマウントしながら起動。
docker run -d --rm -v "./data:/var/lib/data" --name sqlite-with-root sqlite-with-root
ちなみに、同じ内容で compose.yaml
を作る場合は以下の通り。
compose.yaml (※ここでは使いません) services:
sqlite-with-root:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./root/data:/var/lib/data
コンテナが起動したら、 docker exec
で中に入ってDBファイルを読み書きしてみる。
ホスト側 docker exec -it sqlite-with-root sh
コンテナ側 (root) sqlite3 /var/lib/data/db.sqlite "INSERT INTO users (name, email) VALUES ('ユコちゃん', 'yuko-chan@example.com')"
sqlite3 /var/lib/data/db.sqlite "SELECT * FROM users"
コンテナ側結果 1|キリウ君|kiriu-kun@example.com
2|ユコちゃん|yuko-chan@example.com
INSERT
SELECT
ともエラーにはならず、追加したレコードが表示される。
なお、このときコンテナ側から見たDBファイルおよびそのディレクトリのパーミッションは、以下の通りになっている。
コンテナ側 # ls /var/lib/data -la
total 20
drwxr-xr-x 2 1000 1000 4096 Mar 30 20:03 .
drwxr-xr-x 1 root root 4096 Mar 30 20:03 ..
-rw-r--r-- 1 1000 1000 12288 Mar 30 20:03 db.sqlite
この uid/gid 1000 は、ホスト側でこの作業を行っているユーザー のものである。コンテナ内に該当するユーザーがいないため、uid/gid がそのまま表示されている。
非 root ユーザーの場合 今度は以下の Dockerfile
を作成する。こちらはアプリ用のユーザー appuser
(uid/gid 1099) を作成し、コンテナ内の実行ユーザーもそれになるようにしてある。
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y sqlite3
# Add a non-root user
RUN groupadd -g 1099 appuser && \
useradd -r -u 1099 -g appuser appuser
USER appuser
CMD ["tail", "-f", "/dev/null"]
同様にコンテナイメージをビルドして実行。
docker build -t sqlite-with-non-root .
docker run -d --rm -v "./data:/var/lib/data" --name sqlite-with-non-root sqlite-with-non-root
同様に、起動したコンテナに docker exec
で入ってDBファイルを読み書き。
ホスト側 docker exec -it sqlite-with-non-root sh
コンテナ側 (appuser) sqlite3 /var/lib/data/db.sqlite "INSERT INTO users (name, email) VALUES ('ユコちゃん', 'yuko-chan@example.com')"
コンテナ側結果 Error: stepping, attempt to write a readonly database (8)
INSERT
時にエラーとなった。ただし下記のように、 SELECT
はエラーとならず成功した。
コンテナ側 (appuser) sqlite3 /var/lib/data/db.sqlite "SELECT * FROM users"
コンテナ側結果 1|キリウ君|kiriu-kun@example.com
ファイルとディレクトリのパーミッションを変えると OK 前々項で書いたように、コンテナ側から見たDBファイルおよびそのディレクトリは、所有者以外に書き込みができないパーミッションとなっている。
コンテナ側 $ ls /var/lib/data -la
total 20
drwxr-xr-x 2 1000 1000 4096 Mar 30 20:01 .
drwxr-xr-x 1 root root 4096 Mar 30 20:04 ..
-rw-r--r-- 1 1000 1000 12288 Mar 30 20:01 db.sqlite
そこで、ホスト側でこのファイルおよびディレクトリのパーミッションを 777
に変更してみる。(※ディレクトリも変更しないと最初と同じエラーが出てダメ。)
ホスト側 chmod 777 -R ./data
以下がコンテナ側から再度確認したパーミッション。所有者以外も書き込めるようになっている。
コンテナ側 $ ls /var/lib/data -l
total 20
drwxrwxrwx 2 1000 1000 4096 Mar 30 20:01 .
drwxr-xr-x 1 root root 4096 Mar 30 20:04 ..
-rwxrwxrwx 1 1000 1000 12288 Mar 30 20:01 db.sqlite
この状態で再度書き込みを行ってみると、今度は成功する。
コンテナ側 (appuser) sqlite3 /var/lib/data/db.sqlite "INSERT INTO users (name, email) VALUES ('ユコちゃん', 'yuko-chan@example.com')"
sqlite3 /var/lib/data/db.sqlite "SELECT * FROM users"
コンテナ側結果 1|キリウ君|kiriu-kun@example.com
2|ユコちゃん|yuko-chan@example.com
次項に進む前に、本項で変更した DB ファイルとそのディレクトリのパーミッションを元に戻しておく。(ここでは単にホスト側からディレクトリごと削除 -> 再作成を行った。また、マウントしたディレクトリを消してしまうとコンテナ側から認識されなくなるので、併せてコンテナの再起動も行った。)
ファイルとディレクトリの所有者をコンテナ側の実行ユーザーに変えると OK パーミッションを緩めたくない場合、ファイルとディレクトリの所有者をコンテナ側の実行ユーザーに変更することでも、同様にDBファイルへの書き込みを許可できる。
まず、ホスト側にコンテナ側と同じ uid/gid のユーザーを作成する。
ホスト側 sudo groupadd -g 1099 appuser1
sudo useradd -r -u 1099 -g appuser1 appuser1
uid/gid が合ってさえいればよくて、名称は違っていてもOK。また、ホームディレクトリはいらないので useradd
にオプション -r
をつけている。
そしたら、ホスト側でDBファイルとそのディレクトリの所有者をユーザー appuser1
に変更する。(※パーミッションの場合と同様に、ディレクトリも変更しないと当初のエラーが出てダメ。)
ホスト側 sudo chown appuser1:appuser1 -R ./data
以下がコンテナ側から再度確認したパーミッション。uid/gid 通りにコンテナ側の名称が所有者として表示されている。
コンテナ側 $ ls /var/lib/data -la
total 20
drwxr-xr-x 2 appuser appuser 4096 Mar 30 20:20 .
drwxr-xr-x 1 root root 4096 Mar 30 20:20 ..
-rw-r--r-- 1 appuser appuser 12288 Mar 30 20:20 db.sqlite
この状態で再度書き込みを行ってみると、パーミッションを 777
に変更した場合と同様に成功する。
コンテナ側 (appuser) sqlite3 /var/lib/data/db.sqlite "INSERT INTO users (name, email) VALUES ('ユコちゃん', 'yuko-chan@example.com')"
sqlite3 /var/lib/data/db.sqlite "SELECT * FROM users"
コンテナ側結果 1|キリウ君|kiriu-kun@example.com
2|ユコちゃん|yuko-chan@example.com
以上。