Rootless Docker

tags: docker-compose gitpod
  • 一般container執行起來的時候,會是用root的權限在container執行各種檔案的操作
    • 當離開container之後,會發現volume建立的那些檔案都沒有辦法編輯
      • ls -al列出volume底下那些在container建立的檔案都會是root的權限
      • 為了解決這個問題,就需要改用rootless進入container進行後續的操作,但執行npm install會發現又需要root權限…
  • 解決方式有幾種
    • 使用rootless docker(-userns-remap flag),實作方式可以參考下方experimenting-with-rootless-docker的連結
    • 使用docker volume將使用者與群組volume到container環境(要注意需要設定read-only,以免改到本地的群組設定),可以參考using-current-user-when-running-container-in-docker-compose的連結
    • docker build image的時候,使用環境變數將當前登入的使用者與群組也一併新增上去,這是本篇文章採用的作法

Dockerfile

  • 設定環境變數
    • 如果USER_ID和GROUP_ID兩者都沒有設定會被設定為1001
  • 切換root使用者
  • 從環境變數中取得群組編號,並建立群組
  • 新增current_user到image
  • 工作路徑設定為workspace
  • 設定User為current_user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
FROM gitpod/workspace-full

# @see https://dev.to/visuellverstehen/docker-docker-compose-and-permissions-2fih

# Define build arguments
ARG USER_ID
ARG GROUP_ID
ARG USER

# Define environment variables
ENV USER_ID=$USER_ID
ENV GROUP_ID=$GROUP_ID
ENV USER_ID=${USER_ID:-1001}
ENV GROUP_ID=${GROUP_ID:-1001}
ENV CURRENT_USER=$USER

# output message
RUN echo "${CURRENT_USER} is added ${USER_ID} ${GROUP_ID}"

# https://github.com/gitpod-io/workspace-images/blob/master/full/Dockerfile
# RUN as root user
USER root

# Add group and user based on build arguments
RUN addgroup --gid ${GROUP_ID} ${CURRENT_USER}
RUN adduser --disabled-password --gecos '' --uid ${USER_ID} --gid ${GROUP_ID} ${CURRENT_USER}

# npm install permission
RUN sudo chown -R ${USER_ID}:${GROUP_ID} "/home/gitpod/.npm"
RUN sudo chown -R ${USER_ID}:${GROUP_ID} "/home/gitpod/.nvm"

# INSTALL net-tools
RUN apt-get update && apt-get install net-tools

# Set user and group of working directory
WORKDIR /workspace

# RUN as current user
USER ${CURRENT_USER}

docker-compose.yaml

  • 將Dockerfile所需的環境變數在build的階段傳入進來
  • 如果image有設定工作路徑,docker-compose就可以不用另外設定工作路徑
  • 指定對外的port與volume位置
  • 開啟互動模式:(這樣設定完成之後即使下docker-compose up -d沒有服務正在執行,container也不會馬上斷掉)
    • stdin: true
    • tty: true
  • 在container建立起來的時候,執行post-install
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3.2'

services:

hexo-local:
build:
context: .
dockerfile: ./Dockerfile
args:
USER_ID: $USER_ID
GROUP_ID: $GROUP_ID
USER: $USER
working_dir: /workspace # change working directory
volumes:
- ${PWD}:/workspace
ports:
- '8101:80'
stdin_open: true # https://stackoverflow.com/questions/36249744/interactive-shell-using-docker-compose
tty: true
command: sh /workspace/post-install.sh

常用指令

1
2
3
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
export USER=$(whoami)
  • source & build image
1
source env.sh && docker-compose build --no-cache
  • create container via docker-compose
1
docker-compose up -d
  • enter container
1
docker-composer exec hexo-local bash

docker debug技巧

  • image
    • echo可以確認環境變數是否帶入正確
  • container
    • docker run與interactive mode來
    • compose則可以設定tty和stdin為true來進入container
1
docker run --rm -it -v `pwd`:/workspace -p 8101:80 -u 0 gitpod/workspace-full

Reference

experimenting-with-rootless-docker

using-current-user-when-running-container-in-docker-compose

docker-&-docker-compose-and-permissions