Alpine Podman image
精简 Alpine Linux 的开发环境
精简的alpine开发环境
# Use latest Alpine
FROM alpine:latest
RUN apk update && apk upgrade
# Devops utilities
RUN apk add --no-cache openssh openssl bind-tools tmux git neovim
# install system core tools and build-base (C/C++, gdb, compile dependence)
RUN apk add --no-cache \
tini \
su-exec \
bash \
git \
curl \
doas \
build-base \
gdb \
cmake \
linux-headers
# install language develop env
# Python, Node.js, Go
RUN apk add --no-cache \
python3 \
py3-pip \
nodejs \
npm \
go
# install Rust
RUN apk add --no-cache rust cargo
# create admin (UID/GID 1000)
ARG USER=admin
ARG GROUP=admin
ARG UID=1000
ARG GID=1000
RUN addgroup -g ${GID} ${GROUP} && \
adduser -u ${UID} -G ${GROUP} -s /bin/bash -D ${USER} && \
echo "permit nopass :${GROUP}" > /etc/doas.d/doas.conf
# develop enviroment
# Go PATH
ENV GOPATH=/home/${USER}/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
# Rust Cargo bin PATH
ENV PATH=$PATH:/home/${USER}/.cargo/bin
# WorkSpace
WORKDIR /workspace
RUN chown ${USER}:${GROUP} /workspace
# Entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]
CMD ["/bin/bash"]
其中 entrypoint.sh 脚本如下:
entrypoint.sh 提供对Docker环境进行修正
#!/bin/bash
# get HOST UID/GID dynamic (inject by env, default is 1000)
USER_ID=${NEW_UID:-1000}
GROUP_ID=${NEW_GID:-1000}
# if UID changed, fix admin's ID in container
if [ "$USER_ID" != "1000" ]; then
echo "Updating admin UID to $USER_ID..."
sed -i "s/^admin:x:1000:1000:/admin:x:$USER_ID:$GROUP_ID:/" /etc/passwd
sed -i "s/^admin:x:1000:/admin:x:$GROUP_ID:/" /etc/group
fi
# WorkSpace owner right( podman can do it, so remove)
#CURRENT_OWNER=$(stat -c '%u' /workspace)
#if [ "$CURRENT_OWNER" != "$USER_ID" ]; then
# echo "Adjusting permissions for /workspace..."
# chown -R admin:admin /workspace
#fi
# switch to admin, then run commands
# using exec to confirm signal has been forward to sub process
# exec su-exec admin "$@" REPORT ERROR => su-exec: setgroups: Operation not permitted
exec doas -u admin "$@"
构建镜像:
构建镜像
podman build --rm -t alpine-dev .
然后再运行:
运行podman
podman run -d \
--name alpine-dev-toolkit \
--hostname alpine-dev-toolkit \
-p 8080:8080 \
-p 8443:8443 \
-p 9000:9000 \
--user 1000:1000 \
--userns keep-id \
-e LANG=C.UTF-8 \
--workdir /workspace \
-v /home/admin/docs:/workspace:z \
-v admin_home_data:/home/admin \
-v /home/admin/.ssh:/home/admin/.ssh \
--cap-add SYS_PTRACE \
--security-opt seccomp=unconfined \
localhost/alpine-dev_dev-env \
sh -c "sleep infinity"
docker compose运行
为了方便构建,采用 docker compose 来启动容器,即创建 docker-compose.yml :
docker-compose.ymlversion: '3.8'
services:
dev-env:
build:
context: .
dockerfile: Dockerfile
container_name: alpine-dev-toolkit
# use UID Alias map (if userns_mode: "keep-id" ERROR, you can use this underlayer map)
user: "1000:1000" # force container admin
# force admin
# user: "admin"
# Podman special: keep HOST UID same as Container
# if podman-compose report error, please startup with --pod=no
userns_mode: "keep-id"
# override Docker images entrypoint
entrypoint: ["/bin/sh", "-c", "sleep infinity"]
environment:
# when use Podman Rootless, 1000 in container always mapped to HOST's current user
# so we do not need NEW_UID, but remain
- NEW_UID=1000
- NEW_GID=1000
- LANG=C.UTF-8
- TZ=Asia/Shanghai
#- MY_PROJECT_MODE=debug
volumes:
# persistence admin's home directory(include languages cache, config, ssh key, etc)
# "container_home_data" is HOST "~/.local/share/containers/storage/volumes/container_home_data/_data"
- admin_home_data:/home/admin
# :Z means Podman automatic fix SELinux/Ownership
# :U means remap Host directory ownership to Container User, not need chown (Magic)
# :z means Podman mount direcoty can be shared by many containers
- /home/admin/docs:/workspace:rw,z
# special config map
- ~/.ssh/id_rsa:/home/admin/.ssh/id_rsa:ro,z
- ~/.gitconfig:/home/admin/.gitconfig:ro,z
# debug and permit
cap_add:
- SYS_PTRACE # allow GDB debug
security_opt:
# Podman have many limits, so we need disable "seccomp" to permit GDB
- seccomp:unconfined # disable security compute limit
# if Alpine use SELinux, need following line:
- label=disable
# keep container run in background
stdin_open: true
tty: true
volumes:
# define persistent home directory
admin_home_data:
然后执行:
运行
docker compose`docker compose -d .