Docker 用戶管理

Docker 容器啟動之後,預設登入的使用者帳號是 root,這會造成一些困擾,像是編譯過程生成的檔案,將會屬於 root 使用者,之後要進行修改或刪除就會碰到權限的問題。因此泰勞找了幾個方式來管理 Docker 用戶與權限設定的問題,在此簡單介紹。

參考資料:
[Github]tianon/gosu
[Deni Bertovic]Handling permissions with Docker volumes
[redbubble]Running a docker container as a non-root user 

1. --user

第一種方式,透過參數 --user 來指定容器啟動之後的 UID,這樣一來,在容器內生成的檔案都會屬於特定 UID,方便用戶管理。指令簡短易懂,但也有一些缺點,其中之一就是容器無法得知用戶名稱,如下圖所示。

2. useradd

第二種方式,透過 Dockerfile 建立 Docker 映像檔時,直接新增一個使用者並且將其設定為預設用戶。

Dockerfile
FROM ubuntu:18.04

MAINTAINER Kuanlin Chen

RUN useradd -ms /bin/bash build

USER build

接著編譯 Dockerfile 並且執行 Docker 映像檔,可以看到容器啟動之後,預設的用戶已經不再是 root 了,如下圖所示。

3. gosu

使用 gosu 套件主要目的不僅僅是避免使用 root 帳戶,它最重要的功能是將啟動 Docker 容器的用戶 UID 傳入容器內,意即容器外與容器內的 UID 是一樣的。

撰寫一份 Dockerfile 以及啟動容器時需要的腳本,然後編譯一份新的 Docker 映像檔。

Dockerfile
FROM ubuntu:18.04

MAINTAINER Kuanlin Chen

RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get -y --no-install-recommends install ca-certificates curl gnupg


# Install gosu package
RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
RUN curl -o /usr/local/bin/gosu -sSL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture)"
RUN curl -o /usr/local/bin/gosu.asc -sSL "https://github.com/tianon/gosu/releases/download/1.4/gosu-$(dpkg --print-architecture).asc"
RUN gpg --verify /usr/local/bin/gosu.asc
RUN rm /usr/local/bin/gosu.asc
RUN chmod +x /usr/local/bin/gosu

# entrypoint is used to update uid
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod 755 /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

CMD ["bash"]

entrypoint.sh
#!/bin/bash

USER_ID=${DEV_UID:-9001}

echo "Starting with UID : $USER_ID"
useradd --shell /bin/bash -u $USER_ID -o -c "" -m build
export HOME=/home/build
export USER=build

exec /usr/local/bin/gosu build "$@"

編譯完成之後,啟動容器時加入參數 DEV_UID=$(id -u),進入容器即可看到容器內的 UID 就是啟動此容器的用戶 UID,如下圖所示。

以上簡單介紹了三種方式,各有優缺點,泰勞本身是比較喜歡第二種方式,畢竟比較不那麼複雜,但有很多場合是不得不使用 gosu 套件的,所以還是加減練習一下吧!

留言

這個網誌中的熱門文章

程式語言常用之符號與詞彙 - 中英文對照

Repo 實用指令

什麼是 Bootloader?