Initial Rootless Podman Configuration
Goal
Build a rootless podman environment from scratch for a dedicated user podster, and verify it with podman info.
Why it matters
With rootless podman, the configuration is the main part, not the installation. Without a /etc/subuid range, it silently falls back to single-UID mode, permission errors appear only with certain images, and finding the cause takes days. If you do not check graphroot, the home partition fills up and the service stops. If you leave out unqualified-search-registries, a script that worked fine with docker cannot find images with podman.
The checklist in this lab is the exact order used in practice when setting up rootless podman on a new server.
Steps
- Create the
/root/poddirectory, and in/root/pod/user.txtwrite theuid gid 홈경로of the userpodsteron one line, separated by spaces (the placeholders are the uid, the gid, and the home path, in that order). - In
/etc/subuid, assignpodstera range with start 100000 and count 65536. - Assign the same range in
/etc/subgidas well. - Create
/root/pod/mapping.txtwith the following 3 lines.CONTAINER_0=<컨테이너 안 UID 0 에 대응하는 호스트 UID>/CONTAINER_1=<컨테이너 안 UID 1 의 호스트 UID>/CONTAINER_1000=<컨테이너 안 UID 1000 의 호스트 UID>(the placeholders are the host UID that container UID 0 maps to, the host UID of container UID 1, and the host UID of container UID 1000) - Create
/home/podster/.config/containers/storage.conf. The[storage]section must have the three keysdriver,runroot, andgraphroot, andgraphrootmust be/home/podster/.local/share/containers/storage. The file owner must bepodster. - Create
/home/podster/.config/containers/registries.conf.unqualified-search-registriesmust includedocker.io, and there must be a[[registry]]block that sendsdocker.ioto the internal mirrormirror.labhub.local/dockerhub. The file owner must bepodster. - Run
podman infoaspodsterand save the result to/root/pod/info.json. It must be in JSON format, and thegraphRootvalue must be the path you set in step 5. - Create
/root/pod/checklist.txtwith the following 5 lines.SUBUID=yes/SUBGID=yes/ROOTLESS=<info 의 rootless 값 true/false>/GRAPHROOT=<info 의 graphRoot 값>/DRIVER=<info 의 스토리지 드라이버 이름>(the placeholders are the rootless value from info, true or false, the graphRoot value from info, and the storage driver name from info)
Notes
- You assign subuid with
usermod --add-subuids 100000-165535 podsteror by adding one line to/etc/subuid. - To run as that user, use a form like
su - podster -c 'podman info --format json'. - You can use
jqto parse JSON. Example:jq -r '.store.graphRoot' /root/pod/info.json - After creating the configuration directory, do not forget
chown -R podster:podster /home/podster/.config. - Common mistake 1: calculating container UID 1 as 100001 in step 4. The first value of the range corresponds to UID 1.
- Common mistake 2: creating the configuration files owned by root so that podster cannot read them.
Check the target user
Create the /root/pod directory, and in /root/pod/user.txt write the uid gid 홈경로 of the user podster on one line, separated by spaces (the placeholders are the uid, the gid, and the home path, in that order).
You can find the uid, gid, and home directory with the id command. getent passwd is also useful.
Assign the subuid range
In /etc/subuid, assign podster a range with start 100000 and count 65536.
The format is user:start UID:count. You can do it with usermod or by editing the file directly.
Assign the subgid range
Assign the same range in /etc/subgid as well.
It has the same format as subuid. GIDs need a range for the same reason.
Calculate the mapping
Create /root/pod/mapping.txt with the following 3 lines.
CONTAINER_0=<컨테이너 안 UID 0 에 대응하는 호스트 UID> / CONTAINER_1=<컨테이너 안 UID 1 의 호스트 UID> / CONTAINER_1000=<컨테이너 안 UID 1000 의 호스트 UID> (the placeholders are the host UID that container UID 0 maps to, the host UID of container UID 1, and the host UID of container UID 1000)
Container UID 0 maps to the user themselves, and the range starts from 1. Watch the offset.
Write storage.conf
Create /home/podster/.config/containers/storage.conf. The [storage] section must have the three keys driver, runroot, and graphroot, and graphroot must be /home/podster/.local/share/containers/storage. The file owner must be podster.
Per-user configuration goes under .config/containers in the home directory. The [storage] section needs the three keys.
Write registries.conf
Create /home/podster/.config/containers/registries.conf. unqualified-search-registries must include docker.io, and there must be a [[registry]] block that sends docker.io to the internal mirror mirror.labhub.local/dockerhub. The file owner must be podster.
The unqualified search list is an array, and the mirror is written as a [[registry]] block. prefix and location go together.
Verify with podman info
Run podman info as podster and save the result to /root/pod/info.json. It must be in JSON format, and the graphRoot value must be the path you set in step 5.
You must run it as that user for the per-user configuration to take effect. Opening a login shell with su - is safer.
Initial setup checklist
Create /root/pod/checklist.txt with the following 5 lines.
SUBUID=yes / SUBGID=yes / ROOTLESS=<info 의 rootless 값 true/false> / GRAPHROOT=<info 의 graphRoot 값> / DRIVER=<info 의 스토리지 드라이버 이름> (the placeholders are the rootless value from info, true or false, the graphRoot value from info, and the storage driver name from info)
Gather the actual values you confirmed in the earlier steps. Write paths as absolute paths.