在许多地方,你可以读到Podman是Docker的替代品。但是,真的像听起来那么简单吗?在这篇文章中,你将从一个可以立即投入生产使用的Dockerfile开始,并执行Podman命令,就像你使用Docker时会做的那样。让我们看看这是否可以无任何问题地工作!
引言
Podman是一个容器引擎,就像Docker一样。然而,Podman是一个无守护进程的容器引擎,它默认运行的是无根容器(rootless containers)。这比作为根用户运行容器更安全。现在,Docker守护进程也可以作为非根用户运行。
Podman在其网站上宣传,Podman是Docker的替代品。只需添加alias docker=podman ,你就会没问题。让我们看看是否就那么简单。
在本文的余下部分,你将尝试构建一个用于运行Spring Boot应用程序的生产就绪的Dockerfile。你将把它作为一个单独的容器来运行,并且你将尝试运行两个容器并进行一些容器间的通信。最后,你将验证如何挂载卷。本文的一个先决条件是使用Linux操作系统。Podman不适用于Windows。本文使用的源代码可以在GitHub上找到。
你将使用的Dockerfile运行一个Spring Boot应用程序。这是一个基础的Spring Boot应用程序,包含一个返回欢迎消息的控制器。
构建jar文件:
$ mvn clean verify
运行jar文件:
$ java -jar target/mypodmanplanet-0.0.1-SNAPSHOT.jar
检查端点:
$ curl http://localhost:8080/hello
Hello Podman!
文件1-Dockerfile-starter可以在Dockerfiles目录中找到。
FROM eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f AS builder
WORKDIR application
ARG JAR_FILE
COPY target/${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
WORKDIR /opt/app
RUN addgroup --system javauser && adduser -S -s /usr/sbin/nologin -G javauser javauser
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
RUN chown -R javauser:javauser .
USER javauser
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
先决条件
本文的先决条件是:
- 基本的Linux知识,本篇文章中使用的是Ubuntu 22.04;
- 基本的Java和Spring Boot知识;
- 基本的Docker知识。
安装
安装Podman非常简单。只需运行以下命令。
$ sudo apt-get install podman
验证正确的安装。
$ podman --version
podman version 3.4.4
你还可以安装podman-docker,当你在命令中使用docker时,它会创建一个别名。建议等到本篇文章的结论部分再安装这个。
构建Dockerfile
首先要做的是构建容器镜像。从仓库的根目录执行以下命令。
$ podman build . --tag mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT -f Dockerfiles/1-Dockerfile-starter --build-arg JAR_FILE=mypodmanplanet-0.0.1-SNAPSHOT.jar
[1/2] STEP 1/5: FROM eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f AS builder
[2/2] STEP 1/10: FROM eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
Error: error creating build container: short-name "eclipse-temurin@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f" did not resolve to an alias and no unqualified-search registries are defined in "/etc/containers/registries.conf"
这会在检索基础镜像时返回一个错误。错误信息引用了/etc/containers/registries.conf。这个文件中写明了以下内容。
# 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.
总的来说,建议使用全限定的镜像名称。这意味着你需要将含有以下内容的行:
eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
更改为:
docker.io/eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
你只需要在镜像名称前添加docker.io/。这是一个微小的改变,但已经是与Docker的一处不同了。
镜像名称在文件2-Dockerfile-fix-shortname中已经被修正,所以我们再试一次构建镜像。
$ podman build . --tag mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT -f Dockerfiles/2-Dockerfile-fix-shortname --build-arg JAR_FILE=mypodmanplanet-0.0.1-SNAPSHOT.jar
[1/2] STEP 1/5: FROM docker.io/eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f AS builder
Trying to pull docker.io/library/eclipse-temurin@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f...
Getting image source signatures
Copying blob 72ac8a0a29d6 done
Copying blob f56be85fc22e done
Copying blob f8ed194273be done
Copying blob e5daea9ee890 done
[2/2] STEP 1/10: FROM docker.io/eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
Error: error creating build container: writing blob: adding layer with blob "sha256:f56be85fc22e46face30e2c3de3f7fe7c15f8fd7c4e5add29d7f64b87abdaa09": Error processing tar file(exit status 1): potentially insufficient UIDs or GIDs available in user namespace (requested 0:42 for /etc/shadow): Check /etc/subuid and /etc/subgid: lchown /etc/shadow: invalid argument
现在有一个关于用户命名空间中可能的UID或GID不足的错误。你可以在这里找到更多关于此错误的信息。这篇文章非常详细地解释了这个问题,重复所有内容太过繁琐。总的来说,试图拉取的镜像,其文件所属的UID超过了65,536。由于这个问题,镜像无法适应无根Podman的默认UID映射,后者限制了可用的UID和GID数量。
那么,如何解决这个问题呢?
首先,检查/etc/subuid 和 /etc/subgid 的内容。在我的情况下,输出如下。对于你来说,可能会有所不同。
$ cat /etc/subuid
admin:100000:65536
$ cat /etc/subgid
admin:100000:65536
输出中列出的admin用户有100,000作为第一个可用的UID或GID,并且大小为65,536。格式为user:start:size。这意味着admin用户可以访问从100,000到包括165,535在内的UID或GID。
我的当前用户在这里没有列出,这意味着我的用户只能为容器分配1个UID和1个GID。这1个UID/GID已经被容器中的root用户使用了。如果一个容器镜像需要一个额外的用户,就会出现问题,如你在上面所看到的。
这个问题可以通过为你的用户添加UID和GID来解决。让我们给你的用户添加从200,000到包括265,535的值。
$ sudo usermod --add-subuids 200000-265535 --add-subgids 200000-265535 <replace with your user>
再次验证两个文件的内容。用户已添加到两个文件中。
$ cat /etc/subgid
admin:100000:65536
<your user>:200000:65536
$ cat /etc/subuid
admin:100000:65536
<your user>:200000:65536
其次,你需要运行以下命令。
$ podman system migrate
再次尝试构建镜像,现在它可以工作了。
$ podman build . --tag mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT -f Dockerfiles/2-Dockerfile-fix-shortname --build-arg JAR_FILE=mypodmanplanet-0.0.1-SNAPSHOT.jar
[1/2] STEP 1/5: FROM docker.io/eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f AS builder
Trying to pull docker.io/library/eclipse-temurin@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f...
Getting image source signatures
Copying blob f56be85fc22e done
Copying blob f8ed194273be done
Copying blob 72ac8a0a29d6 done
Copying blob e5daea9ee890 done
Copying config c74d412c3d done
Writing manifest to image destination
Storing signatures
[1/2] STEP 2/5: WORKDIR application
--> d4f0e970dc1
[1/2] STEP 3/5: ARG JAR_FILE
--> ca97dcd6f2a
[1/2] STEP 4/5: COPY target/${JAR_FILE} app.jar
--> 58d88cfa511
[1/2] STEP 5/5: RUN java -Djarmode=layertools -jar app.jar extract
--> 348cae813a4
[2/2] STEP 1/10: FROM docker.io/eclipse-temurin:17.0.6_10-jre-alpine@sha256:c26a727c4883eb73d32351be8bacb3e70f390c2c94f078dc493495ed93c60c2f
[2/2] STEP 2/10: WORKDIR /opt/app
--> 4118cdf90b5
[2/2] STEP 3/10: RUN addgroup --system javauser && adduser -S -s /usr/sbin/nologin -G javauser javauser
--> cd11f346381
[2/2] STEP 4/10: COPY --from=builder application/dependencies/ ./
--> 829bffcb6c7
[2/2] STEP 5/10: COPY --from=builder application/spring-boot-loader/ ./
--> 2a93f97d424
[2/2] STEP 6/10: COPY --from=builder application/snapshot-dependencies/ ./
--> 3e292cb0456
[2/2] STEP 7/10: COPY --from=builder application/application/ ./
--> 5dd231c5b51
[2/2] STEP 8/10: RUN chown -R javauser:javauser .
--> 4d736e8c3bb
[2/2] STEP 9/10: USER javauser
--> d7a96ca6f36
[2/2] STEP 10/10: ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
[2/2] COMMIT mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
--> 567fd123071
Successfully tagged localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
567fd1230713f151950de7151da82a19d34f80af0384916b13bf49ed72fd2fa1
像你使用Docker一样,用Podman验证镜像列表:
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/mydeveloperplanet/mypodmanplanet 0.0.1-SNAPSHOT 567fd1230713 2 minutes ago 209 MB
Podman是否可以直接替换Docker来构建Dockerfile?
不,它不是一个直接的替代品,因为你需要在Dockerfile中为基础镜像使用全限定的镜像名称,并且你需要更改用户名称空间以便能够拉取镜像。除了这两个更改之外,构建容器镜像就正常工作了。
启动容器
现在你已经构建了镜像,是时候启动一个容器了。
$ podman run --name mypodmanplanet -d localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
容器已成功启动。
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
27639dabb573 localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT 18 seconds ago Up 18 seconds ago mypodmanplanet
你也可以查看容器日志。
$ podman logs mypodmanplanet
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.5)
2023-04-22T14:38:05.896Z INFO 1 --- [ main] c.m.m.MyPodmanPlanetApplication : Starting MyPodmanPlanetApplication v0.0.1-SNAPSHOT using Java 17.0.6 with PID 1 (/opt/app/BOOT-INF/classes started by javauser in /opt/app)
2023-04-22T14:38:05.898Z INFO 1 --- [ main] c.m.m.MyPodmanPlanetApplication : No active profile set, falling back to 1 default profile: "default"
2023-04-22T14:38:06.803Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-04-22T14:38:06.815Z INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-04-22T14:38:06.816Z INFO 1 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.7]
2023-04-22T14:38:06.907Z INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-04-22T14:38:06.910Z INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 968 ms
2023-04-22T14:38:07.279Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-04-22T14:38:07.293Z INFO 1 --- [ main] c.m.m.MyPodmanPlanetApplication : Started MyPodmanPlanetApplication in 1.689 seconds (process running for 1.911)
验证端点是否可以访问。
$ curl http://localhost:8080/hello
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Connection refused
这是不行的。在Docker中,你可以查看容器以看到为容器分配了哪个IP地址。
$ podman inspect mypodmanplanet | grep IPAddress
"IPAddress": "",
看来容器没有特定的IP地址。端点在localhost上也无法访问。
解决方案是在创建容器时添加端口映射。
停止容器并删除它。
$ podman stop mypodmanplanet
mypodmanplanet
$ podman rm mypodmanplanet
27639dabb5730d3244d205200a409dbc3a1f350196ba238e762438a4b318ef73
再次启动容器,但这次将内部端口8080映射到外部端口8080。
$ podman run -p 8080:8080 --name mypodmanplanet -d localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
再次验证是否可以访问端点。这次可以了。
$ curl http://localhost:8080/hello
Hello Podman!
在继续阅读这个文章之前,请停止并删除容器。
Podman是否可以替代Docker运行容器镜像?
不,它不是可以直接替代的。尽管可以使用与Docker完全相同的命令,但你需要明确添加端口映射。如果没有端口映射,就无法访问端点。
卷挂载
卷挂载以及访问容器外部和容器内部的目录和文件常常导致Permission Denied错误。在之前的文章中,已经详细描述了Docker引擎的这种行为。使用Podman时,看看这是如何工作的会很有趣。
接下来,你将在容器中映射一个application.properties文件,这个文件位于jar文件旁边。Spring Boot应用程序将使用这个application.properties文件。该文件将服务器端口配置为8082端口,并且文件位于存储库根目录下的properties目录中。
server.port=8082
使用端口映射从内部端口8082到外部端口8083来运行容器,并将application.properties文件挂载到容器目录/opt/app中,jar文件也位于这个目录中。卷挂载具有属性ro,以表明它是一个只读文件。
$ podman run -p 8083:8082 --volume ./properties/application.properties:/opt/app/application.properties:ro --name mypodmanplanet localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
验证是否可以访问端点以及它是否工作。
$ curl http://localhost:8083/hello
Hello Podman!
在容器中打开一个shell并列出目录内容以查看文件的所有权。
$ podman exec -it mypodmanplanet sh
/opt/app $ ls -la
total 24
drwxr-xr-x 1 javauser javauser 4096 Apr 15 10:33 .
drwxr-xr-x 1 root root 4096 Apr 9 12:57 ..
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 BOOT-INF
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 META-INF
-rw-r--r-- 1 root root 16 Apr 15 10:24 application.properties
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 org
在Docker中,文件将由您的本地系统用户拥有,但在Podman中,文件由root拥有。我们来检查本地系统上的文件权限。
$ ls -la
total 12
drwxr-xr-x 2 <myuser> domain users 4096 apr 15 12:24 .
drwxr-xr-x 8 <myuser> domain users 4096 apr 15 12:24 ..
-rw-r--r-- 1 <myuser> domain users 16 apr 15 12:24 application.properties
正如你所看到的,本地系统上的文件由拥有。这意味着,运行容器的主机用户,在容器内部被视为root用户。
在容器内打开一个shell,并尝试更改application.properties文件的内容。你会注意到,作为javauser用户,你并不被允许这样做。
$ podman exec -it mypodmanplanet sh
/opt/app $ vi application.properties
/opt/app $ whoami
javauser
停止并删除容器。
运行容器,但这次使用属性U而不是ro。U后缀告诉Podman,根据容器内的UID和GID,使用正确的主机UID和GID来递归地改变源卷的所有者和组。
$ podman run -p 8083:8082 --volume ./properties/application.properties:/opt/app/application.properties:U --name mypodmanplanet localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
在容器中打开一个shell,现在javauser用户是文件的所有者。
$ podman exec -it mypodmanplanet sh
/opt/app $ ls -la
total 24
drwxr-xr-x 1 javauser javauser 4096 Apr 15 10:41 .
drwxr-xr-x 1 root root 4096 Apr 9 12:57 ..
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 BOOT-INF
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 META-INF
-rw-r--r-- 1 javauser javauser 16 Apr 15 10:24 application.properties
drwxr-xr-x 1 javauser javauser 4096 Apr 9 12:57 org
在本地系统中,与我的本地用户不同的UID和GID已经取得了所有权。
$ ls -la properties/
total 12
drwxr-xr-x 2 <myuser> domain users 4096 apr 15 12:24 .
drwxr-xr-x 8 <myuser> domain users 4096 apr 15 12:24 ..
-rw-r--r-- 1 200099 200100 16 apr 15 12:24 application.properties
这次,在本地系统上更改文件是不被允许的,但在容器内的 javauser 用户却可以更改。
Podman 是否可以作为在容器内挂载卷的 Docker 的替代品?
不,它不能替代。文件权限功能与 Docker 引擎有些不同。你需要知道这些区别,以便能够在容器内挂载文件和目录。
Pod
Podman 知道 Pod 的概念,就像 Kubernetes 中的 Pod 一样。Pod 允许你将容器分组。Pod 也有一个共享的网络命名空间,这意味着 Pod 内的容器可以相互连接。有关容器网络的更多信息可以在此找到。这意味着 Pods 是分组容器的首选。当使用 Docker 时,你会使用 Docker Compose 来实现。有像 Podman Compose 这样的东西,但这值得写一篇文章。
让我们看看这是如何工作的。你将设置一个运行两个带有 Spring Boot 应用程序的容器的 Pod。
首先,你需要创建一个 Pod。你还需要暴露你希望在 Pod 之外可以访问的端口。这可以用 -p 参数来实现。并给 Pod 一个名字,在这种情况下是 hello-pod。
$ podman pod create -p 8080-8081:8080-8081 --name hello-pod
当你列出 Pod 时,你会注意到它已经包含一个容器。这就是 infra 容器。这个 infra 容器持有命名空间,以便容器可以相互连接,并且它使 Pod 中的容器启动和停止成为可能。infra 容器基于 k8s.gcr.io/pause 镜像。
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
dab9029ad0c5 hello-pod Created 3 seconds ago aac3420b3672 1
$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aac3420b3672 k8s.gcr.io/pause:3.5 4 minutes ago Created 0.0.0.0:8080-8081->8080-8081/tcp dab9029ad0c5-infra
创建一个名为 mypodmanplanet-1 的容器,并将其添加到 Pod 中。通过 --env 参数,你将 Spring Boot 应用的端口改为 8081。
$ podman create --pod hello-pod --name mypodmanplanet-1 --env 'SERVER_PORT=8081' localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT env
启动 Pod。
$ podman pod start hello-pod
验证是否可以在端口 8081 处访问端点,并验证在端口 8080 处的端点是否无法访问。
$ curl http://localhost:8081/hello
Hello Podman!
$ curl http://localhost:8080/hello
curl: (56) Recv failure: Connection reset by peer
将第二个容器 mypodmanplanet-2 添加到 Pod 中,这次在默认端口 8080 运行。
$ podman create --pod hello-pod --name mypodmanplanet-2 localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT
验证 Pod 状态。它显示状态为 Degraded。
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
dab9029ad0c5 hello-pod Degraded 9 minutes ago aac3420b3672 3
查看容器。有两个容器正在运行,而一个新容器刚被创建。这就是 Pod 状态为 Degraded 的原因。
$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aac3420b3672 k8s.gcr.io/pause:3.5 11 minutes ago Up 2 minutes ago 0.0.0.0:8080-8081->8080-8081/tcp dab9029ad0c5-infra
321a62fbb4fc localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT env 3 minutes ago Up 2 minutes ago 0.0.0.0:8080-8081->8080-8081/tcp mypodmanplanet-1
7b95fb521544 localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT About a minute ago Created 0.0.0.0:8080-8081->8080-8081/tcp mypodmanplanet-2
启动第二个容器并验证 Pod 的状态。现在的状态是运行中。
$ podman start mypodmanplanet-2
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
dab9029ad0c5 hello-pod Running 12 minutes ago aac3420b3672 3
现在可以访问两个端点了。
$ curl http://localhost:8080/hello
Hello Podman!
$ curl http://localhost:8081/hello
Hello Podman!
验证一下,是否可以从mypodmanplanet-2内部访问mypodmanplanet-1的端点。这同样可以实现。
$ podman exec -it mypodmanplanet-2 sh
/opt/app $ wget http://localhost:8081/hello
Connecting to localhost:8081 (127.0.0.1:8081)
saving to 'hello'
hello 100% |***********************************************************************************************************************************| 13 0:00:00 ETA
'hello' saved
清理工作
最后,你可以进行一些清理工作。
停止正在运行的Pod。
$ podman pod stop hello-pod
现在,Pod的状态为Exited。
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
dab9029ad0c5 hello-pod Exited 55 minutes ago aac3420b3672 3
Pod中的所有容器也都处于Exited状态。
$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aac3420b3672 k8s.gcr.io/pause:3.5 56 minutes ago Exited (0) About a minute ago 0.0.0.0:8080-8081->8080-8081/tcp dab9029ad0c5-infra
321a62fbb4fc localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT env 48 minutes ago Exited (143) About a minute ago 0.0.0.0:8080-8081->8080-8081/tcp mypodmanplanet-1
7b95fb521544 localhost/mydeveloperplanet/mypodmanplanet:0.0.1-SNAPSHOT 46 minutes ago Exited (143) About a minute ago 0.0.0.0:8080-8081->8080-8081/tcp mypodmanplane
删除Pod。
$ podman pod rm hello-pod
Pod和容器都被删除。
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
结论
关于Podman是Docker的兼容替代品的说法并不准确。Podman在构建容器镜像、启动容器、网络、卷挂载、容器间通信等方面与Docker存在一些差异。然而,Podman确实支持许多Docker命令。正确的说法应该是Podman是Docker的一种替代选择。 这是完全正确的。在切换到Podman之前,你需要了解并理解这些差异。在了解清楚之后,Podman绝对是一个很好的替代方案。
作者:Gunter Rotsaert
更多技术干货请关注公号“云原生数据库”
squids.cn,基于公有云基础资源,提供云上 RDS,云备份,云迁移,SQL 窗口门户企业功能,
帮助企业快速构建云上数据库融合生态。