Docker コンテナ内で非 sudo 権限でコマンド操作する

PC 環境

  • Thinkpad X1 Intel Core i7
  • Ubuntu 24.04

問題

こちらの branch で Docker コンテナをセットアップして、コンテナ内でコマンド実行すると、自動的に sudo 権限での実行になってしまいます。そのため、以下のようにファイル生成を行うと、owner と group が自動的に root ユーザーになってしまうという弊害があります。

Docker コンテナ内

remma@remma-ThinkPad-X1-Carbon-Gen-11:~/lab/ros2_nav2$ docker exec -it ros2_nav2 bash
root@remma-ThinkPad-X1-Carbon-Gen-11:/workspace# echo a > tmp.txt
root@remma-ThinkPad-X1-Carbon-Gen-11:/workspace# ls -l tmp.txt 
-rw-r--r-- 1 root root 2 Feb 23 10:31 tmp.txt

ホスト環境(Docker コンテナ外)

remma@remma-ThinkPad-X1-Carbon-Gen-11:~/lab/ros2_nav2/workspace$ ls -l tmp.txt 
-rw-r--r-- 1 root root 2 Feb 23 19:31 tmp.txt

対策

上述の問題を回避するために新たに .env ファイルを生成し、docker-compose.yml と Dockerfile を以下のように変更します。

変更後の Docker 関連ファイル

生成した .env ファイル、変更後の docker-compose.yml, Dockerfile ファイルはそれぞれ以下です。github repository はこちら。branch 名は article_7372 です。

同じディレクトリに以下の 3 ファイルを置いて docker compose up -d --build を実行すれば、コンテナが立ち上がります。

UID=1000
GID=1000

※ ubuntu 環境だと一般的に UID, GID はそれぞれ 1000 になりますが、これらは環境によって異なるのでご自身の環境で以下を実施し、実行結果を UID, GID に入力してください。

$ id -u  # UID の確認
$ id -g  # GID の確認
version: '3.9'

services:
  ros2_nav2:
    build:
      context: .
      args:
        UID: "${UID}"
        GID: "${GID}"
    container_name: ros2_nav2
    network_mode: "host"
    user: "${UID}:${GID}"
    environment:
      - DISPLAY=${DISPLAY}
      - QT_X11_NO_MITSHM=1
      - XAUTHORITY=/root/.Xauthority
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
      - $XAUTHORITY:/root/.Xauthority
      - ./workspace:/workspace:rw
    stdin_open: true
    tty: true
FROM ros:humble

ENV DEBIAN_FRONTEND=noninteractive

ARG UID=1000
ARG GID=1000
RUN groupadd -g $GID usergroup && \
    useradd -m -u $UID -g usergroup -G sudo user && \
    echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

RUN apt update && apt install -y \
    vim \
    ros-humble-rviz2 \
    ros-humble-navigation2 \
    ros-humble-nav2-bringup \
    ros-humble-turtlebot3-gazebo && \
    rm -rf /var/lib/apt/lists/*

RUN echo "source /opt/ros/humble/setup.bash" >> /home/user/.bashrc

WORKDIR /workspace

CMD ["bash"]

実行結果

上記のようにファイルを追加・変更した上で以下を実行し、Docker コンテナを再ビルド & up してみましょう。

$ docker compose down --volumes
$ docker compose build --no-cache
$ docker compose up -d

その上で、Docker コンテナ内でファイルを作ると、ファイルの owner が root ではなくなります。

Docker コンテナ内

remma@remma-ThinkPad-X1-Carbon-Gen-11:~/lab/ros2_nav2$ docker exec -it ros2_nav2 bash
user@remma-ThinkPad-X1-Carbon-Gen-11:/workspace$ echo a > tmp2.txt
user@remma-ThinkPad-X1-Carbon-Gen-11:/workspace$ ls -l tmp2.txt 
-rw-r--r-- 1 user usergroup 2 Feb 23 10:51 tmp2.txt

ホスト環境(Docker コンテナ外)

remma@remma-ThinkPad-X1-Carbon-Gen-11:~/lab/ros2_nav2/workspace$ ls -l tmp2.txt
-rw-r--r-- 1 remma remma 2 Feb 23 19:51 tmp2.txt

変更点説明

git diff コマンドで出力した変更点をもとに、変更の意味を解説していきます。

.env

UID=1000
GID=1000

.env ファイルでは UID(ユーザー ID)と GID(グループ ID)を指定します。

docker-compose.yml

-    build: .
+    build:
+      context: .
+      args:
+        UID: "${UID}"
+        GID: "${GID}"

上記により、Dockerfile に .env で指定された UID, GID の値を渡してビルドします。

     container_name: ros2_nav2
     network_mode: "host"
+    user: "${UID}:${GID}"

コンテナ内のプロセスの UID, GID を .env で指定したものにして実行します。

Dockerfile

+ARG UID=1000
+ARG GID=1000

UID, GID のデフォルト値を 1000 とします(docker-compose.yml から変数が与えられた場合はその変数で上書かれる)。

+RUN groupadd -g $GID usergroup && \
+    useradd -m -u $UID -g usergroup -G sudo user && \
+    echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
  • groupadd コマンドの -g オプションで $GID に対応するグループ usergroup を作成する。
  • useradd コマンドで $UID に対応するユーザー user を作成する。
    • -m オプションで /home/user にホームディレクトリを作成。
    • -u オプションでユーザー ID を $UID に指定。
    • -g オプションでユーザーが属するプライマリグループを usergroup に指定。
    • -G sudo で user を sudo グループに追加し、管理者権限を持たせる。
  • user が sudo を実行する際にパスワードを要求しないようにする。

以下のように Docker コンテナ内で sudo 権限でコマンドを実行することができます。このときパスワードは不要です。

remma@remma-ThinkPad-X1-Carbon-Gen-11:~/lab/ros2_nav2$ docker exec -it ros2_nav2 bash
user@remma-ThinkPad-X1-Carbon-Gen-11:/workspace$ sudo apt update
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]                      
Get:2 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]                                
Get:3 http://packages.ros.org/ros2/ubuntu jammy InRelease [4682 B]                      
Get:4 http://packages.ros.org/ros2/ubuntu jammy/main amd64 Packages [1650 kB]
...
-RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc
+RUN echo "source /opt/ros/humble/setup.bash" >> /home/user/.bashrc

.bashrc の格納先を root ディレクトリから /home/user に変更しています。

参考

コメント