[Linux] podman 和 podman-compose 个人使用记录 (解决podman-compose目录所有权变更问题)
说明
Podman
是一个类似于Docker
的工具,不过相比于Docker
,它的最大特点就是默认使用无root
模式运行,并且没有守护进程。如果要实现容器自动运行,通常来说需要systemd
来实现。
对我个人来说,Podman
的无root
理念是极好的,至少确实是更安全了,如果是docker
,容器被入侵的情况下可能会有危险,但是podman
使用普通账户运行时不会有过多的权限。
但是这个特性本身也带来了别的问题,因为podman-compose
对挂载目录的奇怪支持,导致podman
启动的容器绑定的目录所有权会改变,此时如果用的不是root
账户,就没办法通过宿主机访问到被挂载的这个目录。
podman
在新版的yum/dnf
系系统上被用于替代docker,从源中安装的docker
实际上是podman
,执行的docker
命令实际上是podman
的一层壳,本质会将docker
命令行参数转换为podman
的参数。大多数参数都可以没有问题的被兼容,但是还有少量参数不完全相同,导致一些问题的出现,比如和网络相关的参数。(所以很反感这种帮用户做决定的行为)
各种项目一般只提供了docker-compose.yml
,但是这个文件有时候不能被podman-compose
解释执行,就会让人有些闹心。
但是总的来说,这个也确实是未来的一个方向,也是一种主流的可能,所以还是可以学学看的
简单的命令
容器相关
podman run #创建并启动容器
podman start #启动容器
podman ps #查看容器
podman stop #终止容器
podman restart #重启容器
podman attach #进入容器
podman exec #进入容器
podman export #导出容器
podman import #导入容器快照
podman rm #删除容器
podman logs #查看日志
podman stats #查看所有容器的状态
镜像相关
podman search #检索镜像
docke pull #获取镜像
podman images #列出镜像
podman image Is #列出镜像
podman rmi #删除镜像
podman image rm #删除镜像
podman save #导出镜像
podman load #导入镜像
podmanfile #定制镜像(三个)
podman build #构建镜像
podman run #运行镜像
podmanfile #常用指令(四个)
COPY #复制文件
ADD #高级复制
CMD #容器启动命令
ENV #环境变量
EXPOSE #暴露端口
一些常用操作
- 查看所有运行的容器
podman ps
,使用podman ps -a
查看所有容器 - 在容器内部执行一个命令
podman exec syncthing ls -lh /
将会在容器内执行ls命令,列出/里面的文件列表
如果是podman exec -it syncthing sh
则可以进入容器的命令行 - 换源
两个配置文件/etc/containers/registries.conf
和~/.config/containers/registries.conf
前者是全局的,后者是用户配置
我的方案比较简单,因为有梯子的原因我的配置只有unqualified-search-registries = ["docker.io"]
具体可参考 docker,podman配置国内镜像国内源 - 掘金 (juejin.cn) - 生成一个systemd的unit文件以实现开机启动
podman generate systemd --restart-policy always --files --new --name syncthing
可以修改生成的unit
文件以添加指定选项,比如--userns keep-id
podman-compose
其使用的配置文件还是docker-compose.yml
但是,对其支持并不是很完整,有的指令是不支持的,需要具体情况具体分析
官方文档Overview | Docker Docs
参考文档Compose 模板文件 - Docker — 从入门到实践 (gitbook.io)
常用操作
#启动容器
podman-compose up
# 后台启动
podman-compose up -d
# 停止并删除容器
podman-compose down
解决podman-compose所有权改变问题
当我通过docker-compose.yml启动一个容器,例如
version: "3"
services:
syncthing:
image: syncthing/syncthing
container_name: syncthing
hostname: my-syncthing
environment:
#- PUID=1000
#- PGID=1000
#user: "1000:1000"
volumes:
- ./st-sync:/var/syncthing
ports:
- 8384:8384 # Web UI
- 22000:22000/tcp # TCP file transfers
- 22000:22000/udp # QUIC file transfers
- 21027:21027/udp # Receive local discovery broadcasts
restart: unless-stopped
宿主机目录./st-sync
的所有权就变成了一个不存在的uid
和gid
(在我的电脑上是100999
),导致我的普通账户没办法访问
如果是podman直接启动容器,那么使用 --userns keep-id
参数应该就可以了,但是docker-compose.yml
中没有这样的东西
其提供的user
指令可以生效,宿主机的所有权变成指定的了,但是容器里面的所有权又乱了,导致容器没办法工作(简单起见,你可以使用chmod 777 -R data
将文件权限改成777
以便让容器有权限访问,但是,,,感觉不太合理)。这个导致的原因似乎和uid
映射有关系。
总之目前没有很好的解决方案,目前的解决方案如下
podman-compose 有没有办法传递“--userns keep-id”参数? ·期刊 #166 ·容器/podman-compose (github.com)
思路是将参数通过环境变量直接传递给podman
如果希望所有容器都如此,那么就把export PODMAN_USERNS=keep-id
放到.bashrc
文件中
要么配合docker-compose.yml
文件中的env_file
选项从文件中获取环境变量
总之,podman-compose
为什么不解决这个问题,真的想不明白。。。(好像1.0.6版本没问题?不过rockylinux
源中的版本目前还是1.0.3
)
开启自启动
同时,如果你想让podman-compose
拉起的容器开机自启动,并且使用systemd
,同时能够保持--unserns keep-id
选项,通常步骤如下
podman-compose up -d
podman generate systemd --restart-policy always --files --new --name syncthing
- 修改
~/.config/systemd/user/container-syncthing.service
文件添加启动参数 systemctl --user enable container-syncthing
- 如果是普通账户,还需要
root
运行loginctl enable-linger <普通账号名>
避免退出所有shell
后服务关闭的问题
之后开机就会自动拉起,并且没有所有权被切换的问题了
实际上
podman run
本身是支持--env-file
选项的,但是不知道为啥不起作用
一些yml文件
都是自己使用的备忘,具体使用见项目官方
lychee
version: "3"
services:
lychee:
image: lycheeorg/lychee:dev
container_name: lychee
stdin_open: true
tty: true
restart: always
ports:
- 8801:80
volumes:
- ./conf:/conf:z
- ./uploads:/uploads:z
- ./sym:/sym:z
jellyfin
version: "3"
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
stdin_open: true
tty: true
restart: always
ports:
- 8805:8096
volumes:
- ./config:/config:z
- ./cache:/cache:z
- /export/data:/media:z
#privileged: true
emby
version: "3.9"
services:
emby:
image: amilys/embyserver:beta
container_name: emby
ports:
- 8096:8096
- 8920:8920
- 1900:1900/udp
- 7359:7359/udp
environment:
- PUID=1000
- PGID=1000
- GIDLIST=0
- TZ=Asia/Shanghai
volumes:
- ./emby:/config
- ./media:/media
restart: unless-stopped
navidrome
version: "3"
services:
navidrome:
image: deluan/navidrome:sha-4ccb6cc
user: 1000:1000 # should be owner of volumes
container_name: navidrome
userns_mode: keep-id
userns_name: host
ports:
- "8803:4533"
restart: always
environment:
# Optional: put your config options customization here. Examples:
ND_SCANSCHEDULE: 1h
ND_LOGLEVEL: info
ND_SESSIONTIMEOUT: 36000h
ND_BASEURL: ""
volumes:
- ./data:/data:rw
- /export/data/music/:/music:rw
privileged: true