[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的所有权就变成了一个不存在的uidgid(在我的电脑上是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
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
posted @ 2024-03-04 00:00  Startu  阅读(892)  评论(0编辑  收藏  举报