Podman 容器

我最近完成了在 OpenWrt 24.10.2运行 Podman 的完整过程并对其进行了配置,使其能够良好地与 OpenWrt 原生的网络、防火墙设置以及守护进程的启动和配置逻辑协同工作。 https://openwrt.org/docs/guide-user/virtualization/docker_host 上的部分信息已经过时,我已在该页面更新了部分内容,并在此分享这份更完整的指南,供希望获得更实用操作流程的用户参考。


运行

opkg install podman

它会自动安装依赖,包括网络工具和container runtimes。


将Podman的存储路径更改到有足够空间的磁盘或者目录。因为容器的大小和数量会占据更多空间:

/etc/containers/storage.conf:

graphroot = "/home/podman/storage"

然后创建该目录:

mkdir -p /home/podman/storage

添加一个定时任务:

crontab -e
# Podman cleanup
10 0 * * 0 /usr/bin/podman system prune --volumes -f > /dev/null 2>&1
20 0 * * 0 /usr/bin/podman image prune -a -f > /dev/null 2>&1

希望 Podman 使用 static bridge 并且由OpenWrt的网络配置和防火墙进行完全管理。 以下是设置方法:

/etc/containers/networks/podman.json:

{
     "name": "podman",
     "driver": "bridge",
     "network_interface": "podman0",
     "subnets": [
          {
               "subnet": "192.168.11.0/24",
               "gateway": "192.168.11.1"
          }
     ],
     "ipv6_enabled": false,
     "internal": false,
     "dns_enabled": true,
     "ipam_options": {
          "driver": "host-local"
     }
}

/etc/containers/containers.conf:

[network]
network_backend = "netavark"
firewall_driver = "none"
network_config_dir = "/etc/containers/networks/"
default_network = "podman"
default_subnet = "192.168.11.0/24"
default_rootless_network_cmd = "slirp4netns"

/etc/config/network:

config device
        option type 'bridge'
        option name 'podman0'
        option bridge_empty '1'
        option ipv6 '0'
config interface 'podman0'
        option proto 'static'
        option device 'podman0'
        option ipaddr '192.168.11.1'
        option netmask '255.255.255.0'

/etc/config/firewall:

注意,区域(zone)的名称必须与你的实际配置相匹配。

config zone
        option name 'Podman'
        option input 'DROP'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'podman0'
config forwarding
        option src 'Podman'
        option dest 'Internet'
config forwarding
        option src 'lan'
        option dest 'Podman'
config rule
        option name 'DNS to Podman'
        option src 'Podman'
        option dest_port '53'
        option target 'ACCEPT'

由于 firewall_driver = “none”,Podman 不会自动开放端口。 如果需要让容器能够被访问,必须手动创建相应的防火墙规则。 正因如此,我明确地为每个容器分配一个固定的 IP 地址,下文将详细介绍这一做法。

示例:

config rule
        option src 'VPN'
        option name 'NRPE to Nagios'
        option dest_port '5666'
        option target 'ACCEPT'
        list proto 'tcp'
        list src_ip '192.168.0.5'
        option dest 'Podman'
config redirect
        option dest 'Podman'
        option target 'DNAT'
        option name 'Serve NRPE from container'
        option family 'ipv4'
        list proto 'tcp'
        option src 'VPN'
        option src_dport '5666'
        option dest_ip '192.168.11.2'
        option dest_port '5666'
        option src_ip '192.168.0.5'

以下是我使用初始化脚本在系统启动时运行容器的方法。 该脚本支持的参数较为基础,在容器名称和镜像方面需要自己检查,但对我而言已足够使用,也很容易修改。 它通过 /etc/config/containers 进行配置,具有较高的灵活性。

#!/bin/sh /etc/rc.common
 
START=90
STOP=20
USE_PROCD=1
 
NAME=containers
PROG=/usr/bin/podman
 
. /lib/functions.sh
 
start_service() {
    # At boot time, wait longer for dependencies
    local max_wait=60
    local count=0
 
    logger -t "$NAME" "Waiting for system readiness"
 
    # Wait for basic system services
    while [ $count -lt $max_wait ]; do
        # Check if essential services are ready
        if [ -S /var/run/ubus/ubus.sock ] && pgrep -f "ubusd" >/dev/null && \
           [ -d /sys/class/net ] && $PROG system info >/dev/null 2>&1; then
            break
        fi
        sleep 1
        count=$((count + 1))
    done
 
    if [ $count -ge $max_wait ]; then
        logger -t "$NAME" "Timeout waiting for system services and podman to be ready"
        return 1
    fi
 
    logger -t "$NAME" "Starting containers service"
 
    config_load containers
    config_foreach start_container container
}
 
start_container() {
    local cfg="$1" enabled name
 
    config_get enabled "$cfg" enabled 0
    config_get privileged "$cfg" privileged 0
    config_get name "$cfg" name "$cfg"
    config_get image "$cfg" image "$cfg"
 
    config_get dns "$cfg" dns ""
    config_get hostname "$cfg" hostname ""
    config_get image "$cfg" image ""
    config_get ip "$cfg" ip ""
    config_get memory "$cfg" memory ""
    config_get pid "$cfg" pid ""
    config_get pull "$cfg" pull "missing"
    config_get restart "$cfg" restart ""
 
    caps=""
    append_cap() {
        caps="$caps --cap-add=$1"
    }
    config_list_foreach "$cfg" cap append_cap
 
    envs=""
    append_env() {
        envs="$envs -e $1"
    }
    config_list_foreach "$cfg" env append_env
 
    vols=""
    append_vol() {
        vols="$vols -v $1"
    }
    config_list_foreach "$cfg" volume append_vol
 
    [ "$enabled" -eq 0 ] && return 0
 
    logger -t "$NAME" "Starting container $name"
    logger -t "$NAME" "Pulling latest version for $name - $image"
 
    $PROG pull $image  >/dev/null 2>&1 || logger -t "$NAME" "Pulling failed for $image"
 
    # Build the Podman command
    podman_cmd="$PROG run -d"
    [ -n "$dns" ] && podman_cmd="$podman_cmd --dns $dns"
    [ -n "$hostname" ] && podman_cmd="$podman_cmd --hostname $hostname"
    [ -n "$ip" ] && podman_cmd="$podman_cmd --ip $ip"
    [ -n "$memory" ] && podman_cmd="$podman_cmd --memory $memory"
    [ -n "$pid" ] && podman_cmd="$podman_cmd --pid $pid"
    [ -n "$restart" ] && podman_cmd="$podman_cmd --restart $restart"
    [ "$privileged" -eq 1 ] && podman_cmd="$podman_cmd --privileged"
    podman_cmd="$podman_cmd $envs $vols $caps --name $name $image"
 
    logger -t "$NAME" "Running '$podman_cmd'"
 
    procd_open_instance "$name"
    procd_set_param command sh -c "
        $podman_cmd || exit 1
        exec $PROG wait '$name'
    "
    procd_set_param respawn
    procd_close_instance
}
 
stop_service() {
    config_load containers
    config_foreach stop_container container
}
 
stop_container() {
    local cfg="$1" name
    config_get name "$cfg" name "$cfg"
    $PROG stop "$name" 2>/dev/null
    $PROG rm "$name" 2>/dev/null
}
 
# Standard init handlers
start() { start_service; }
stop() { stop_service; }
restart() { stop; start; }
reload() { stop; start; }

赋予可执行权限

chmod +x /etc/init.d/containers

使其开机自启动

/etc/init.d/containers enable

/etc/config/containers:

config container 'test'
    option enabled '1'
    option privileged '0'
    option name 'test'
    option dns '9.9.9.9'
    option image 'quay.io/podman/hello'
    option memory '64m'
    option hostname 'hello'
    option ip '192.168.11.2'
    option pid 'host'
    option restart 'unless-stopped'
    list env 'TZ=Europe/Amsterdam'
    list volume '/etc/openwrt_release:/etc/openwrt_release:ro'
    list volume '/home/test_container/etc/:/etc/test'
    list cmd 'ping'
    list cmd '-c'
    list cmd '4'
    list cmd '192.168.11.1'

将以下内容添加到: /etc/sysupgrade.conf

/etc/containers
/etc/config/containers
/etc/init.d/containers
/home/

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2025/09/02 09:40
  • by starsfall