MacOS 환경에서 podman 설치하기 #3
지난 번 MacOS 환경에서 podman 설치하기 #2에서 docker.io/golang 이미지는 오류 엇이 정상적으로 가지고 오는 것을 확인 했었지만 바로 golang으로 이미지 가져오기를 시도하면 오류가 발생했었다. 이렇게 docker.io와 같은 registry 표기 없이 사용하는 것을 short-name 을 사용한다고 표현 한다.
$ podman pull golang Error: short-name resolution enforced but cannot prompt without a TTY
사실 docker의 경우는 registry host를 지정하지 않은 경우 docker hub를 기본 registry로 인식한다. 따라서, 초기의 상당수의 Dockerfile에서는 이를 생략한 형태로 만들어 놓는 경우가 많았었다. 근데, conatiner가 보편화 되고 표준화 되면서 container registry에서도 이를 구분지어 사용하게 되었다. podman의 경우는 docker가 아니므로 short name 이미지 저장소를 궂이 docker hub로 인식하는 것을 기본이 아니다.
아래와 같이 short-name으로 base Image를 사용하는 간단한 Dockerfile을 만들어 테스트 해보자.
$ podman build -t hello-reids .
STEP 1/3: FROM redis
Error: error creating build container: short-name resolution enforced but cannot prompt without a TTY
오류 메시지에 의하면 TTY가 없는 경우(지금과 같이 API Client를 이용하는 경우)는 short-name을 선택 하는 prompt를 보여줄 수 없기 때문에 컨테이너 빌드가 실패 했다고 한다. 그럼 모든 이미지에 대해 registry 정보를 추가해 주면 해결이 되겠지만 기존에 작성해 놓은 Dockerfile을 변경해야 한다던지 또는 기존 docker CLI의 동작과 다른 경우를 궂이 경험하고 싶지 않는 경우가 있을 수 있다.
마침 short-name에 대해 잘 설명을 해 놓은 글이 있으니 이를 참고해 보자.
https://www.redhat.com/sysadmin/container-image-short-names
Podman short name에 대하여
위의 글에 따르면 podman의 image short name에 대한 정책은 /etc/containers/registries.conf 파일에 설정할 수 있다고 되어 있다. 이 파일은 Podman Server로 사용 중인 VM에 있으므로 vagrant ssh로 접속해서 확인해 볼 수 있다.
다음은 Fedora VM의 registries.conf 파일이다. 내용이 좀 길어서 여기서 comment 처리가 되어 있지 않는 부분만 대략 추려 보았다.
# For more information on this configuration file, see containers-registries.conf(5).
#
# NOTE: RISK OF USING UNQUALIFIED IMAGE NAMES
# We recommend always using fully qualified image names including the registry
# server (full dns name), namespace, image name, and tag
# (e.g., registry.redhat.io/ubi8/ubi:latest). Pulling by digest (i.e.,
# quay.io/repository/name@digest) further eliminates the ambiguity of tags.
# When using short names, there is always an inherent risk that the image being
# pulled could be spoofed. For example, a user wants to pull an image named
# `foobar` from a registry and expects it to come from myregistry.com. If
# myregistry.com is not first in the search list, an attacker could place a
# different `foobar` image at a registry earlier in the search list. The user
# would accidentally pull and run the attacker's image and code rather than the
# intended content. We recommend only adding registries which are completely
# trusted (i.e., registries which don't allow unknown or anonymous users to
# create accounts with arbitrary names). This will prevent an image from being
# spoofed, squatted or otherwise made insecure. If it is necessary to use one
# of these registries, it should be added at the end of the list.
#
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io", "quay.io"]
#
# .....
#
# Enforcing mode for short names is default for Fedora 34 and newer
short-name-mode="enforcing"
short-name-mode 키에 대한 값에 따라 short name을 모드를 설정 할 수 있다. 각 모드에 대해서는 다음과 같이 containers/image의 container registries.conf 문서에 Short-Name Aliasing에 대한 설명하고 있다.
내용을 정리하면 다음과 같다.
- enforcing : usqualified-search 레지스트리에 단일로 설정이 되어 있는 경우, 이를 사용함에 있어서 혼동이 없다. 만약, 하나보다 많은 레지스트리들이 설정되어 있는 경우 그리고 사용자 프로그램이 터미널 (TTY와 같은 표준 입출력 장치)에서 실행 중인 경우는 사용자에게 검색용 레지스트리로 선택 것을 할지 보여준다. 사용자 프로그램이 터미널에서 실행 중이 아니라면, 레지스트리 사용에 대한 혼동 문제를 해결을 할 수 없으므로 에러로 이어진다.
- permissive : enforcing과 비슷하게 동작하지만 터미널에서 실행중이 아니라도 오류로 이어지게 하지 않는다. 그 대신 unqualified-search에 있는 모든 레지스트리를 다 이용하게 된다.
- disabled : 사용자에게 묻지 않고 모든 unqualified-search에 있는 모든 레지스트리를 다 이용하게 된다.
Fedora 배포판에서는 short-name-mode 값이 기본적으로 enforcing이다. 이 때문에 지난 번 MacOS 환경에서 podman 설치하기 #2에서 Vagrant ssh로 VM에서 podman pull golang을 실행할 때 prompt를 보여주고 registry를 선택하도록 했었었다.
MacOS podman에서는 TTY 환경이 아니므로 이런 Prompt를 보여줄 수가 없었기 때문에 오류 메시지가 나온 것이었다. 따라서, 이 값을 permissive 로 변경주면 short name을 사용해도 오류가 발생하지 않는다.
# Enforcing mode for short names is default for Fedora 34 and newer
short-name-mode="permissive"
이제 이미지를 build 명령을 실행하면 unqualified-search에 있는 모든 레지스트리들에서 redis를 조회하게 되며, docker.io에서 등록된 redis 이미지를 찾아 다운로드 하는 것을 볼 수 있다.
$ podman build -t hello-redis .
STEP 1/3: FROM redis
Resolving "redis" using unqualified-search registries (/etc/containers/registries.conf)
Trying to pull registry.fedoraproject.org/redis:latest...
Trying to pull registry.access.redhat.com/redis:latest...
Trying to pull docker.io/library/redis:latest...
Getting image source signatures
Copying blob sha256:0b88638a5b778b573dd7c4e3fda17cab7d4b229defd7943a07ac982c65e98cbb
Copying blob sha256:e1acddbe380c63f0de4b77d3f287b7c81cd9d89563a230692378126b46ea6546
Copying blob sha256:a31098369fccd4adaac914a87e5def0f96dc1dbc385921d38db1f1f4cef8242a
Copying blob sha256:4a49b0eba86d37bb4fa4d1a9f8826a1222ea4eb7717192674d79341a998febf8
Copying blob sha256:fddf1399eface27528e89bb5296dc40fbabe7c6b2186c0fca6dce96ae9c5d9a1
Copying blob sha256:5c6658b59b7200ac5a9ec19f428dc5739a95ea2f6965715443692bff6da9a79d
Copying blob sha256:e1acddbe380c63f0de4b77d3f287b7c81cd9d89563a230692378126b46ea6546
Copying blob sha256:5c6658b59b7200ac5a9ec19f428dc5739a95ea2f6965715443692bff6da9a79d
Copying blob sha256:0b88638a5b778b573dd7c4e3fda17cab7d4b229defd7943a07ac982c65e98cbb
Copying blob sha256:fddf1399eface27528e89bb5296dc40fbabe7c6b2186c0fca6dce96ae9c5d9a1
Copying blob sha256:a31098369fccd4adaac914a87e5def0f96dc1dbc385921d38db1f1f4cef8242a
Copying blob sha256:4a49b0eba86d37bb4fa4d1a9f8826a1222ea4eb7717192674d79341a998febf8
Copying config sha256:ddcca4b8a6f0367b5de2764dfe76b0a4bfa6d75237932185923705da47004347
Writing manifest to image destination
Storing signatures
STEP 2/3: RUN echo "hello world"
hello world
--> 78845c9f4ab
STEP 3/3: CMD ["echo", "Hello world"]
COMMIT hello-redis
--> ea860a2c794
Successfully tagged localhost/hello-redis:latest
ea860a2c7946af8f7c48bb43ea6edf2cda25be27d4dda865beb91d7b5ef67534
만약, 어짜피 사용자에게 선택할 수 없는 경우라면, short-name-mode를 enforcing 상태로 그대로 두고 unqualified-search에 docker.io 만 남겨두는 방법을 선택하거나, 아예 short-name-mode를 disabled 상태로 설정하는 방법을 이용해도 된다.
단, diabled로 설정 할 때 주의 해야 할 점이 있는데, short name에 대한 registry를 사용자가 명확하게 선택 할 수 없기 때문에 unqualified-search-registries에 등록된 registry들을 순차적으로 확인하게 되며, 가장 먼저 해당 이미지를 제공하는 registry에서 이미지를 이미지를 우선 다운로드 하게 된다. 따라서, docker와 유사하게 동작하도록 하고자 한다면 docker.io를 가장 먼저 나오도록 다음과 같이 우선 순위를 변경하는 방법을 사용할 수 있다.
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
unqualified-search-registries = ["docker.io", "registry.fedoraproject.org", "registry.access.redhat.com", "quay.io"]
registry.fedoraproject.org를 먼저 조회 했던 것와 달리 docker.io 부터 먼저 검색하는 것을 볼 수 있다.
podman build -t hello-redis .
STEP 1/3: FROM redis
Resolving "redis" using unqualified-search registries (/etc/containers/registries.conf)
Trying to pull docker.io/library/redis:latest...
Getting image source signatures
Copying blob sha256:0b88638a5b778b573dd7c4e3fda17cab7d4b229defd7943a07ac982c65e98cbb
Copying blob sha256:e1acddbe380c63f0de4b77d3f287b7c81cd9d89563a230692378126b46ea6546
...
short-name-mode="enforcing" 상태에서도 오류가 안난다?
참고로, unqualified-search-registries에 여러 개의 registry가 등록되어 있고, 또 short-name-mode가 기본값인 enforcing 상태에서 터미널에서 실행 중이 아닌 상황에서도 오류없이 이미지를 가져오는 경우가 있다.
다음과 Dockerfile을 이용해 보자.
FROM busybox
RUN echo "hello world"
CMD ["echo", "Hello world"]
위 Dockerfile을 이용해서 podman으로 이미지를 생성하려고 하면 TTY 오류 메시지 없이 정상 동작한다. 왜일까?
$ podman build -t hello .
STEP 1/3: FROM busybox
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob sha256:8ec32b265e94aafb0d43ab71f1d8f786122c19afb37d25532aea169f414f8881
Copying blob sha256:8ec32b265e94aafb0d43ab71f1d8f786122c19afb37d25532aea169f414f8881
Copying config sha256:42b97d3c2ae95232263a04324aaf656dc80e7792dee6629a9eff276cdfb806c0
Writing manifest to image destination
Storing signatures
STEP 2/3: RUN echo "hello world"
hello world
--> 6af95a70618
STEP 3/3: CMD ["echo", "Hello world"]
COMMIT hello
--> 893421ba684
Successfully tagged localhost/hello:latest
893421ba68468c3b7b55150e290a3a8c9798fc2ec501ebb6623b3d770329c711
short-name-mode 설정에 따르면 원칙적으로는 오류가 발생해야 한다. 하지만, podman은 사람들에게 일반적으로 많이 알려진 이미지들에 대해서는 alias로 미리 등록해 놓았고 이 정보를 이용해서 해당 shortname을 인식하므로 오류가 발생하지 않는다. 이 정보는
/etc/containers/registries.conf.d/000-shortnames.conf 파일에 저장되어 있으며, Vagrant VM의 내용 중 busybox 이미지에 대해서는 다음과 같이 정의되어 있는 것을 확인 해 볼 수 있다.
정리하며
어느정도 docker cli처럼 podman을 사용할 준비가 된 것 같다. 앞서 build 한 이미지들을 정리하기 위해 podman images 명령으로 생성된 이미지를 확인했다.
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/hello latest 893421ba6846 7 hours ago 1.46 MB
docker.io/library/busybox latest 42b97d3c2ae9 12 days ago 1.46 MB
그리고, 이 이미지로 컨테이너를 만들어 실행하면 다음과 같은 결과를 볼 수 있다.
$ podman run localhost/hello
Hello world
만약 앞서 생성한 이미지 삭제를 하려 하면 이미 사용 중인 이미지라고 나오면서 직접 삭제가 되지 않는다.
$ podman rmi localhost/hello
Error: Image used by c14cf31a39cbd4905219160f96b8f5813a445459072add9979aa5b21c8b1dc17: image is in use by a container
이 경우는 docker와 마찬가지로 podman ps -a 명령으로 컨테이너를 조회한 후
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c14cf31a39cb localhost/hello:latest echo Hello world 8 hours ago Exited (0) 8 hours ago zen_driscoll
해당 컨테이너를 삭제한 다음에야 이미지를 삭제가 가능하다.
$ podman rm c14cf31a39cb
c14cf31a39cb
$ podman rmi localhost/hello
Untagged: localhost/hello:latest
Deleted: 893421ba68468c3b7b55150e290a3a8c9798fc2ec501ebb6623b3d770329c711
Deleted: 6af95a706189467e2d86c611708e85416ae2fe1d1cfb5f0eb395446e67b94c65
마무리
얼추 이 정도면 어느정도 docker desktop을 대체 할 수 있는 것으로 볼 수 있지 않을까 싶다. 그렇다면 docker-compose는 podman을 이용할 수 없을까?라는 질문이 자연스럽게 떠오르는데 역시나 이미 준비가 되어 있었다.
https://github.com/containers/podman-compose
하지만, 이건 좀 시간을 두고 확인해 봐야겠다.