Skip to content

Commit

Permalink
Support minimal tag, change uid/gid, remove stuff
Browse files Browse the repository at this point in the history
Changes:
* Builds a `minimal` image (without slirp4netns) instead of `rootless`.
* `podman` uid/gid changed from 100000 to 1000/1000 (to avoid exceeding the sub*id range).
* Default USER is root now.
* No ENTRYPOINT script provided that changes the user when container is run as root.
* The HOME env var is not specified anymore in order to use the home dir specified for the user in /etc/passwd.
* Default WORKDIR has changed from /podman to / since /podman is only relevant when running as `podman` user.
  • Loading branch information
mgoltzsche committed Dec 25, 2020
1 parent 4a6f17b commit 76cb4c4
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 99 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:

env:
PODMAN_IMAGE: podman
PODMAN_ROOTLESS_IMAGE: podman-rootless
PODMAN_MINIMAL_IMAGE: podman-minimal
PODMAN_REMOTE_IMAGE: podman-remote

jobs:
Expand All @@ -25,7 +25,7 @@ jobs:
uses: actions/checkout@v2

- name: Build & Test
run: make podman podman-rootless podman-remote test
run: make podman podman-minimal podman-remote test

- name: Build signed archive
run: make signed-tar
Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
# Expand tags: 1.2.3 -> 1 1.2 1.2.3
TAGS="$(echo "$TAGS" | sed -E -e 's/^((([0-9]+)\.[0-9]+)\.[0-9]+)$/\3 \2 \1/')"
for IMAGE in $PODMAN_REMOTE_IMAGE $PODMAN_IMAGE $PODMAN_ROOTLESS_IMAGE; do
for IMAGE in $PODMAN_REMOTE_IMAGE $PODMAN_IMAGE $PODMAN_MINIMAL_IMAGE; do
TAG_SUFFIX=$(echo $IMAGE | sed -E -e 's/^([^-]+)//')
LATEST_TAG="$([ "$TAG_SUFFIX" ] && echo $TAG_SUFFIX | sed -E -e 's/^-//' || echo latest)"
[ "$TAGS" == "master" ] && IMAGE_TAGS="$LATEST_TAG" || IMAGE_TAGS="$LATEST_TAG $TAGS"
Expand Down
28 changes: 11 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -130,31 +130,24 @@ COPY --from=gosu /usr/local/bin/gosu /usr/local/bin/gosu
COPY --from=conmon /conmon/bin/conmon /usr/libexec/podman/conmon
COPY --from=podman /usr/local/bin/podman /usr/local/bin/podman
COPY conf/containers /etc/containers
COPY entrypoint.sh /entrypoint.sh
RUN set -ex; \
adduser -D podman -h /podman -u 100000; \
echo 'podman:100001:65536' > /etc/subuid; \
echo 'podman:100001:65536' > /etc/subgid; \
adduser -D podman -h /podman -u 1000; \
echo 'podman:100000:65536' > /etc/subuid; \
echo 'podman:100000:65536' > /etc/subgid; \
ln -s /usr/local/bin/podman /usr/bin/docker; \
mkdir -p /podman; \
chmod 1777 /podman; \
mkdir -p /podman/.local/share/containers/storage /var/lib/containers/storage; \
chown -R podman:podman /podman; \
mkdir -m1777 /.local /.config; \
podman --help >/dev/null; \
/usr/libexec/podman/conmon --help >/dev/null
WORKDIR /podman
ENV HOME=/podman
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "sh" ]
ENV _CONTAINERS_USERNS_CONFIGURED=""

# Build rootless podman base image (without OCI runtime)
FROM podmanbase AS rootlesspodmanbase
ENV BUILDAH_ISOLATION=chroot container=oci
RUN apk add --no-cache shadow-uidmap
COPY --from=fuse-overlayfs /usr/bin/fuse-overlayfs /usr/local/bin/fuse-overlayfs
COPY --from=fuse-overlayfs /usr/bin/fusermount3 /usr/local/bin/fusermount3
COPY --from=slirp4netns /slirp4netns/slirp4netns /usr/local/bin/slirp4netns
RUN set -ex; \
slirp4netns --help >/dev/null; \
fuse-overlayfs --help >/dev/null

# Build rootless podman base image with runc
FROM rootlesspodmanbase AS rootlesspodmanrunc
Expand All @@ -171,13 +164,14 @@ RUN set -ex; \
chmod +x /usr/local/bin/crun; \
crun --help >/dev/null

# Build rootless podman base image with crun
FROM rootlesspodmanbase AS rootlesspodmancrun
# Build minimal rootless podman
FROM rootlesspodmanbase AS rootlesspodmanminimal
COPY --from=crun /usr/local/bin/crun /usr/local/bin/crun
COPY conf/rootless-crun-containers.conf /etc/containers/containers.conf
COPY conf/crun-containers.conf /etc/containers/containers.conf

# Build podman image with rootless binaries and CNI plugins
FROM rootlesspodmanrunc AS podmanall
RUN apk add --no-cache iptables ip6tables
COPY --from=slirp4netns /slirp4netns/slirp4netns /usr/local/bin/slirp4netns
COPY --from=cniplugins /usr/libexec/cni /usr/libexec/cni
COPY conf/cni /etc/cni
70 changes: 39 additions & 31 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,48 +1,57 @@
PODMAN_IMAGE_TAG ?= latest
PODMAN_IMAGE_NAME ?= mgoltzsche/podman
PODMAN_IMAGE ?= $(PODMAN_IMAGE_NAME):$(PODMAN_IMAGE_TAG)
PODMAN_ROOTLESS_IMAGE ?= $(PODMAN_IMAGE)-rootless
PODMAN_IMAGE ?= $(PODMAN_IMAGE_NAME):latest
PODMAN_IMAGE_TARGET ?= podmanall
PODMAN_REMOTE_IMAGE_NAME ?= mgoltzsche/podman-remote
PODMAN_REMOTE_IMAGE ?= $(PODMAN_REMOTE_IMAGE_NAME):$(PODMAN_IMAGE_TAG)
PODMAN_MINIMAL_IMAGE ?= $(PODMAN_IMAGE)-rootless
PODMAN_REMOTE_IMAGE ?= $(PODMAN_IMAGE)-remote
PODMAN_SSH_IMAGE ?= mgoltzsche/podman-ssh

GPG_IMAGE=gpg-signer

ASSET_NAME=podman-linux-amd64
BUILD_DIR=build/$(ASSET_NAME)

DOCKER ?= $(if $(shell podman -v),podman,docker)

images: podman podman-rootless podman-remote
images: podman podman-remote podman-minimal

podman:
docker build --force-rm -t $(PODMAN_IMAGE) --target $(PODMAN_IMAGE_TARGET) .
$(DOCKER) build --force-rm -t $(PODMAN_IMAGE) --target $(PODMAN_IMAGE_TARGET) .

podman-rootless:
make podman PODMAN_IMAGE=$(PODMAN_ROOTLESS_IMAGE) PODMAN_IMAGE_TARGET=rootlesspodmancrun
podman-minimal:
make podman PODMAN_IMAGE=$(PODMAN_MINIMAL_IMAGE) PODMAN_IMAGE_TARGET=rootlesspodmanminimal

podman-remote:
docker build --force-rm -t $(PODMAN_REMOTE_IMAGE) -f Dockerfile-remote .
$(DOCKER) build --force-rm -t $(PODMAN_REMOTE_IMAGE) -f Dockerfile-remote .

podman-ssh: podman-rootless
docker build --force-rm -t $(PODMAN_SSH_IMAGE) -f Dockerfile-ssh --build-arg BASEIMAGE=$(PODMAN_ROOTLESS_IMAGE) .
podman-ssh: podman
$(DOCKER) build --force-rm -t $(PODMAN_SSH_IMAGE) -f Dockerfile-ssh --build-arg BASEIMAGE=$(PODMAN_IMAGE) .

test: test-rootless-image test-local-rootless test-local-rootful test-remote
test: test-local-rootless test-local-rootful test-minimal-image test-remote

test-local-rootful: podman
test-local-rootful: podman storage-dir
IMAGE=$(PODMAN_IMAGE) ./test/test-local-rootful.sh

test-local-rootless: podman
test-local-rootless: podman storage-dir
IMAGE=$(PODMAN_IMAGE) ./test/test-local-rootless.sh

test-rootless-image: podman-rootless
IMAGE=$(PODMAN_ROOTLESS_IMAGE) TEST_PREDICATE=ROOTLESS ./test/test-local-rootless.sh
test-minimal-image: podman-minimal storage-dir
IMAGE=$(PODMAN_MINIMAL_IMAGE) TEST_PREDICATE=MINIMAL SKIP_PORTMAPPING_TEST=true ./test/test-local-rootless.sh

test-remote: podman-rootless podman-remote
PODMAN_IMAGE=$(PODMAN_ROOTLESS_IMAGE) \
storage-dir: clean-storage-dir
mkdir -p test/storage/root
mkdir -pm 1777 test/storage/user

clean-storage-dir:
$(DOCKER) run --rm -v "`pwd`/test:/test" alpine:3.12 rm -rf /test/storage

test-remote: podman podman-remote
PODMAN_IMAGE=$(PODMAN_IMAGE) \
PODMAN_REMOTE_IMAGE=$(PODMAN_REMOTE_IMAGE) \
./test/test-remote.sh

install:
cp -r build/podman-linux-amd64/usr build/podman-linux-amd64/etc /

tar: .podman-from-container
rm -f $(BUILD_DIR).tar.gz
tar -C build -czvf $(BUILD_DIR).tar.gz $(ASSET_NAME)
Expand All @@ -54,19 +63,19 @@ tar: .podman-from-container
cp -r conf/cni $(BUILD_DIR)/etc/cni
cp README.md $(BUILD_DIR)/
set -e; \
CONTAINER=`docker create $(PODMAN_IMAGE)`; \
CONTAINER=`$(DOCKER) create $(PODMAN_IMAGE)`; \
for BINARY in podman runc fusermount3 fuse-overlayfs slirp4netns; do \
docker cp $$CONTAINER:/usr/local/bin/$$BINARY $(BUILD_DIR)/usr/local/bin/; \
$(DOCKER) cp $$CONTAINER:/usr/local/bin/$$BINARY $(BUILD_DIR)/usr/local/bin/; \
done; \
docker cp $$CONTAINER:/usr/libexec/podman $(BUILD_DIR)/usr/libexec/podman; \
docker cp $$CONTAINER:/usr/libexec/cni $(BUILD_DIR)/usr/libexec/cni; \
docker rm $$CONTAINER
$(DOCKER) cp $$CONTAINER:/usr/libexec/podman $(BUILD_DIR)/usr/libexec/podman; \
$(DOCKER) cp $$CONTAINER:/usr/libexec/cni $(BUILD_DIR)/usr/libexec/cni; \
$(DOCKER) rm $$CONTAINER

signed-tar: tar .gpg
@echo Running gpg signing container with GPG_SIGN_KEY and GPG_SIGN_KEY_PASSPHRASE
export GPG_SIGN_KEY
export GPG_SIGN_KEY_PASSPHRASE
@docker run --rm -v "`pwd`/build:/build" \
@$(DOCKER) run --rm -v "`pwd`/build:/build" \
-e GPG_SIGN_KEY="$$GPG_SIGN_KEY" \
-e GPG_SIGN_KEY_PASSPHRASE="$$GPG_SIGN_KEY_PASSPHRASE" \
$(GPG_IMAGE) /bin/sh -c ' \
Expand All @@ -93,20 +102,19 @@ verify-signature:
)

.gpg:
docker build --force-rm -t $(GPG_IMAGE) --target gpg .
$(DOCKER) build --force-rm -t $(GPG_IMAGE) --target gpg .

run:
docker run -ti --rm --privileged \
$(DOCKER) run -ti --rm --privileged \
-v "`pwd`/test/storage/user":/podman/.local/share/containers/storage \
$(PODMAN_IMAGE) /bin/sh

clean:
clean: clean-storage-dir
rm -rf build
docker run --rm -v "`pwd`/test:/test" alpine:3.12 rm -rf /test/storage

run-server: podman-ssh
# TODO: make sshd log to stdout (while still ensuring that we know when it is available)
docker run --rm --privileged --network=host \
$(DOCKER) run --rm --privileged --network=host \
-v "`pwd`/storage/user":/podman/.local/share/containers/storage \
-v "`pwd`/test:/build" \
-w /build \
Expand All @@ -123,7 +131,7 @@ run-server: podman-ssh
# TODO: fix build run for external client
# see ssh connection: https://github.com/containers/podman/blob/v2.0.4/pkg/bindings/connection.go#L73
run-client: podman-remote
docker run --rm -it --network=host \
$(DOCKER) run --rm -it --network=host \
-v "`pwd`/test:/build" \
-w /build \
-e PODMAN_URL=ssh://[email protected]:2222/tmp/podman/podman.sock?secure=True \
Expand Down
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# podman binaries and container image ![GitHub workflow badge](https://github.com/mgoltzsche/podman-static/workflows/Release/badge.svg)
# podman binaries and container images ![GitHub workflow badge](https://github.com/mgoltzsche/podman-static/workflows/Release/badge.svg)

This project provides alpine-based podman container image variants and statically linked (rootless) podman binaries for linux-amd64 along with its dependencies _(without systemd support)_:
This project provides alpine-based podman container images and statically linked (rootless) podman binaries for linux-amd64 along with its dependencies _(without systemd support)_:
* [podman](https://github.com/containers/podman)
* [runc](https://github.com/opencontainers/runc/) or [crun](https://github.com/containers/crun)
* [conmon](https://github.com/containers/conmon)
Expand All @@ -15,21 +15,28 @@ The following image tags are supported:
| Tag | Description |
| --- | ----------- |
| `latest`, `<VERSION>` | podman with both rootless and rootful dependencies: runc, conmon, fuse-overlayfs, slirp4netns, CNI plugins. |
| `rootless`, `<VERSION>-rootless` | podman with crun (configured to use host cgroup), fuse-overlayfs, slirp4netns and conmon. |
| `minimal`, `<VERSION>-minimal` | podman, crun, fuse-overlayfs and conmon binaries, configured to use the host's existing namespaces (low isolation level). |
| `remote`, `<VERSION>-remote` | the podman remote binary. |

Please note that, when running podman within a docker container, the docker container needs to be `--privileged`.
By default containers are run as user `root`. However the `podman` (uid/gid 1000) user can be used instead for which also a subuid/gid mapping is provided with the image (as described within the binary installation section below).

As a workaround for docker the entrypoint script changes the owner of the storage volume mount point (`$HOME/.local/share/containers/storage`) to the unprivileged user `podman` (100000, `HOME=/podman`) before it runs the provided command.
Though the entrypoint script can be omitted and a container can be run with any unprivileged user explicitly since the image is user agnostic - though the default uid/gid map only supports the `podman` user.
The storage directory within the container depends on the user's `HOME` directory:

| User | Storage directory |
| ---- | ----------------- |
| `root` | `/var/lib/containers/storage` |
| `podman` | `/podman/.local/share/containers/storage` |
| other | `/.local/share/containers/storage` |

Please note that, when running non-remote podman within a docker container, the docker container needs to be `--privileged`.

### Container usage example

Run podman in docker:
```sh
docker run --privileged mgoltzsche/podman:rootless docker run alpine:latest echo hello from nested container
```
_Within the container `docker` is linked to `podman` to support applications that require `docker`._
_Within the container `docker` is linked to `podman` to support applications that use the `docker` command._

## Binary installation on a host

Expand All @@ -44,17 +51,25 @@ curl -fsSL -o podman-linux-amd64.tar.gz.asc https://github.com/mgoltzsche/podman
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 0CCF102C4F95D89E583FF1D4F8B5AF50344BB503
gpg --batch --verify podman-linux-amd64.tar.gz.asc podman-linux-amd64.tar.gz
```
_This may fail every now and then due to desync/unavailable key servers. Please retry in that case._
_This may fail every now and then due to desync/unavailable key servers. In that case please retry._

Install the binaries and configuration on your host after you've inspected the archive:
```sh
tar -xzf podman-linux-amd64.tar.gz
sudo cp -r podman-linux-amd64/usr podman-linux-amd64/etc /
```
_If you have docker installed on the same host it will be broken until you remove the newly installed `/usr/local/bin/runc` binary since docker is not compatible with the latest runc version provided here while podman is also compatible with the older runc version that comes with docker._

In order to run rootless containers that use multiple uids/gids you may want to set up a uid/gid mapping for your user on your host:
```
sudo sh -c "echo $(id -un):100000:65536 >> /etc/subuid"
sudo sh -c "echo $(id -gn):100000:65536 >> /etc/subgid"
```
_Please make sure you don't add the mapping multiple times._

To support applications that require the `docker` command you may want to link it to `podman` as follows:
To support applications that use the `docker` command you may want to link it to `podman` as follows:
```sh
sudo ln -s /usr/local/bin/podman /usr/bin/docker
sudo ln -s /usr/local/bin/podman /usr/local/bin/docker
```

### Binary usage example
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# See https://github.com/containers/common/blob/master/pkg/config/containers.conf
# and https://github.com/containers/podman/blob/master/contrib/podmanimage/stable/containers.conf
[containers]
netns="host"
userns="host"
ipcns="host"
utsns="host"
cgroupns="host"
cgroups="disabled"
[engine]
Expand Down
14 changes: 0 additions & 14 deletions entrypoint.sh

This file was deleted.

22 changes: 11 additions & 11 deletions test/test-local-rootful.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,14 @@ cd "$(dirname $0)"
set -eu

echo
echo TEST PODMAN AS ROOT '(using CNI)'
echo TEST PODMAN AS ROOT - NETWORKING '(using CNI)'
echo
(set -x; docker run --rm --privileged --entrypoint /bin/sh \
-u root:root \
-v "`pwd`/storage/root":/var/lib/containers/storage \
"${IMAGE}" \
-c 'podman run --rm alpine:3.12 wget -O /dev/null http://example.org')

echo
echo TEST PODMAN AS ROOT - PORT MAPPING
echo
(set -x; docker run --rm --privileged --entrypoint /bin/sh \
-u root:root \
-v "`pwd`/storage/root":/var/lib/containers/storage \
--mount "type=bind,src=`pwd`/test-portmapping.sh,dst=/test-portmapping.sh" \
"${IMAGE}" \
-c /test-portmapping.sh)

echo
echo TEST PODMAN DOCKERFILE BUILD AS ROOT
echo
Expand All @@ -36,3 +26,13 @@ echo
RUN echo hello world > /hello
CMD ["/bin/cat", "/hello"]
EOF')

echo
echo TEST PODMAN AS ROOT - PORT MAPPING
echo
(set -x; docker run --rm --privileged --entrypoint /bin/sh \
-u root:root \
-v "`pwd`/storage/root":/var/lib/containers/storage \
--mount "type=bind,src=`pwd`/test-portmapping.sh,dst=/test-portmapping.sh" \
"${IMAGE}" \
-c /test-portmapping.sh)
Loading

0 comments on commit 76cb4c4

Please sign in to comment.