boot2podman.github.io

2020-07-22 afbjorklund

Machine Replacement

If you are looking for a replacement for podman-machine or docker-machine,
you can use Vagrant to provision a virtual machine with Fedora or Ubuntu.

Since both podman and docker are now available as standard distro packages, installation is just a yum or an apt away (the deb package is called “docker.io”).

Manage as non-root user

If you install the normal package, you will have to use sudo to run it. This becomes a problem, when trying to access the service from remote…

But it is possible to add a system group, to be used instead of root, so that additional users can have socket access - without having to use sudo.

https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user

Create the docker group.

$ sudo groupadd docker

Add your user to the docker group.

$ sudo usermod -aG docker $USER

This also means that we can use a unix socket, instead of a tcp port:

unix://[/path/to/socket]

tcp://[host]:[port][path]

We use ssh to access this socket remotely, rather than a separate port.

The group means that we don’t have to log in as root, but as normal user.

Security

Note that being part of this group allows running privileged containers:

Warning: The docker group grants privileges equivalent to the root user.

It is also possible to run rootless containers, but that is not the topic here.

We assume that the user is already part of the sudoers without a password.

Vagrant with VirtualBox

Save to a Vagrantfile, and use vagrant up to boot the virtual machine.

Podman (Fedora)

Vagrant.configure("2") do |config|
  config.vm.box = "fedora/32-cloud-base"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end

  config.vm.provision "shell", inline: <<-SHELL
    yum install -y podman

    groupadd -f -r podman

    #systemctl edit podman.socket
    mkdir -p /etc/systemd/system/podman.socket.d
    cat >/etc/systemd/system/podman.socket.d/override.conf <<EOF
[Socket]
SocketMode=0660
SocketUser=root
SocketGroup=podman
EOF
    systemctl daemon-reload
    echo "d /run/podman 0770 root podman" > /etc/tmpfiles.d/podman.conf
    systemd-tmpfiles --create

    systemctl enable podman.socket
    systemctl start podman.socket

    usermod -aG podman $SUDO_USER
  SHELL
end

Docker (Ubuntu)

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
    # focal64 bug: https://bugs.launchpad.net/cloud-images/+bug/1829625
    vb.customize [ "modifyvm", :id, "--uartmode1", "file", File::NULL ]
  end

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update && apt-get install -y docker.io

    systemctl disable snapd.socket snapd.service
    systemctl stop snapd.socket snapd.service

    systemctl enable docker.socket docker.service
    systemctl start docker.socket docker.service

    usermod -aG docker $SUDO_USER
  SHELL
end

Access

The virtual machine has been booted, and systemd has enabled the socket.

You can now use the vagrant ssh command, to access the virtual machine.

vagrant ssh -c "sudo podman version"
vagrant ssh -c "sudo podman info"

Have to use sudo here, or it would still try to run the rootless podman.

vagrant ssh -c "docker version"
vagrant ssh -c "docker info"

Provider

By default vagrant uses the “virtualbox” provider, available on all platforms.

It is also possible to use the “libvirt”/kvm provider when running on Linux.

But you probably have to use the “generic” images, from the Vagrant Cloud:

Only the provider changes in the Vagrantfile, provisioning stays the same:

Vagrant.configure("2") do |config|
  config.vm.box = "generic/fedora32"

  config.vm.provider "libvirt" do |lv|
    lv.memory = "1024"
  end

  ...

Configure client

Previously we would use podman varlink or the docker port 2376 to access, but now both of them are using unix sockets over ssh connections instead…

Use vagrant up to start and vagrant ssh-config to see the configuration. Then use variables from this ssh_config, to configure the ssh connection:

Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile $PWD/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

Podman Remote

export CONTAINER_HOST=ssh://vagrant@127.0.0.1:2222/run/podman/podman.sock
export CONTAINER_SSHKEY=$PWD/.vagrant/machines/default/virtualbox/private_key

You currently have to supply the path of the unix socket, or it gets confused:

ssh: rejected: connect failed (open failed)

Note that podman uses CONTAINER_HOST and Containerfile, and not “podman”.

Docker CLI

export DOCKER_HOST=ssh://vagrant@127.0.0.1:2222 # /var/run/docker.sock
ssh-add -k .vagrant/machines/default/virtualbox/private_key

When using docker it is not supported to supply the path of the unix socket:

ssh host connection is not valid: extra path after the host

The docker client doesn’t support ssh identity, so the ssh-agent is used here.

Rootless

To run a rootless podman socket as the user instead, you can use this setup:

Vagrant.configure("2") do |config|
  config.vm.box = "fedora/32-cloud-base"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end

  config.vm.provision "shell", privileged: false, inline: <<-SHELL
    sudo yum install -y podman

    systemctl enable --user podman.socket
    systemctl start --user podman.socket
  SHELL
end
$ export CONTAINER_HOST=ssh://vagrant@127.0.0.1:2222/run/user/1000/podman/podman.sock
$ export CONTAINER_SSHKEY=$PWD/.vagrant/machines/default/virtualbox/private_key
$ podman-remote --url $CONTAINER_HOST version
Client:
Version:      2.0.4
API Version:  1
Go Version:   go1.14.2
Built:        Thu Jan  1 01:00:00 1970
OS/Arch:      linux/amd64

Server:
Version:      2.0.4
API Version:  0
Go Version:   go1.14.6
Built:        Thu Jan  1 01:00:00 1970
OS/Arch:      linux/amd64

Previous information: