# Use podman with Lima

# Introduction

If you landed on this blog post, you are most likely migrating from Docker Desktop to another container tool. If you have chosen Podman Desktop as your alternative, this is the right place for you to learn how to take advantage of the compatibility of such tool with `lima`, the most famous tool to quickly and effortlessly run a virtualized **Li**nux **Ma**chine.

This guide is based on macOS, but it can be of inspiration also for people trying to achieve the same thing on Windows (or why not, on Linux itself).

## What is lima?

The term `lima` is a shorter for “**li**nux **ma**chine”, and it is a CLI utility that can be quickly installed running:

```bash
brew install lima
```

This tool allows to specify, through a `.yaml` configuration file, how the Linux VM should look like. For example:

* which Linux distribution to use;
    
* cores, RAM and disk to allocate to the VM;
    
* which commands to run at instantiation time as sudo user;
    
* which commands to run at instantiation time as normal user;
    
* how to create the connection from the VM to the host machine (through SSH tunneling or through socket).
    

`lima` comes with some predefined templates that the user can override. In our case we will be using a `fedora` template and then add on top our own customisations.

## What is Podman?

`podman` is a container engine built by RedHat and publicly available for everyone. The tool is very similar to `docker`, especially in terms of CLI commands. However the `podman` engine can run in a unique mode called `rootless`, meaning that it doesn’t require any `root` permission to run (as opposed to `docker`, where the `daemon` runs as root).

If you have installed **Podman Desktop** on your machine, you may have already seen that it comes with:

* a prepackaged VM (called `podman-machine-default`);
    
* a set of extensions, one of which is the **Lima extension**. `podman` can indeed smoothly speak with other `lima` VMs once they are set.
    

## Create a lima VM for `podman`

Here I share a template to create a `lima` VM which will be set to use `runc` as container runtime (as opposed to `podman-machine-default` which uses `crun`). This machine could be useful if you, for example, have some issues with the `—-memory-swappiness` option, which unfortunately will not work with `crun` .

The template is the following:

```yaml
minimumLimaVersion: 1.1.0

# VM settings (adapt them to your needs)
cpus: 4
memory: "16GiB"
disk: "100GiB"

# base templates
base:
  - template://_images/fedora-41
  - template://_default/mounts

# disable containerd to be sure podman is the only container
# engine running in the system
containerd:
  system: false
  user: false

# scripts to setup your VM
provision:
    # script being run as sudo user
  - mode: system
    script: |
      #!/bin/bash
      set -eux -o pipefail
      command -v podman >/dev/null 2>&1 && test -e /etc/lima-podman && exit 0

      # Install podman AND runc
      dnf -y install --best podman runc podman-docker && touch /etc/lima-podman

      # Configure runc as default runtime
      mkdir -p /etc/containers
      printf '%s\n' \
        '[engine]' \
        'runtime = "runc"' \
        '' \
        '[engine.runtimes]' \
        'runc = ["/usr/bin/runc"]' \
        'crun = ["/usr/bin/crun"]' \
        > /etc/containers/containers.conf
    # script being run as normal user
  - mode: user
    script: |
      #!/bin/bash
      set -eux -o pipefail

      # Copy runtime config to user directory
      mkdir -p ~/.config/containers
      cp /etc/containers/containers.conf ~/.config/containers/

      # Your existing service enable
      systemctl --user enable --now podman.socket

# script performed to consider the VM healthy
probes:
  - script: |
      #!/bin/bash
      set -eux -o pipefail
      if ! timeout 30s bash -c "until command -v podman >/dev/null 2>&1; do sleep 3; done"; then
        echo >&2 "podman is not installed yet"
        exit 1
      fi
    hint: See "/var/log/cloud-init-output.log" in the guest

# connection mechanism between host and VM
portForwards:
  - guestSocket: "/run/user/{{.UID}}/podman/podman.sock"
    hostSocket: "{{.Dir}}/sock/podman.sock"

# message print at startup
message: |
  To run `podman` on the host (assumes podman-remote is installed), run the following commands:
  ------
  podman system connection add {{.Name}} "unix://{{.Dir}}/sock/podman.sock"
  podman system connection default {{.Name}}
  podman{{if eq .HostOS "linux"}} --remote{{end}} run quay.io/podman/hello
  ------
```

Take the template above and create a template:

```bash
vim ~/.lima/_config/podman.yaml
```

At this point, create the VM by running:

```bash
limactl create --name=podman ~/.lima/_config/podman.yaml
```

The name can be different, but if you name it `podman` as in the example you will see it also in Podman Desktop appearing, since the Lima extension expects the Lima VM to be called either `podman` or `docker`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1751568063409/18bb8bff-35f9-457d-ba80-7e4a4022b11f.png align="center")

Once the VM has been created, start it with:

```bash
limactl start podman
```

If everything goes fine, you should now have a full Linux VM running on your machine. You can double check it by running:

```bash
limactl list
# example of output showing the podman machine up and running
NAME      STATUS     SSH                VMTYPE    ARCH       CPUS    MEMORY    DISK      DIR
podman    Running    127.0.0.1:57384    vz        aarch64    4       16GiB     100GiB    ~/.lima/podman
```

You can even log into the machine by running:

```bash
limactl shell podman
```

## Connect `podman` with the Lima VM

At this point, you’re almost done. The only thing missing is to connect `podman` on the host side with the just created VM. To do it, run:

```bash
podman system connection add podman "unix:///$HOME/.lima/podman/sock/podman.sock"
podman system connection default podman
```

At this point, you’re good to go!

You can test now that everything runs as expected by running:

```bash
podman run --rm hello-world
```

## Bonus 1: make `podman` compatible with `docker`

If you are used with the `docker` CLI in your scripts/programs, there is no need to switch them to `podman` since `podman` is fully compatible with `docker`.

If you want to achieve this, copy the following script as `/usr/local/bin/docker`:

```bash
#!/bin/sh
[ -e /etc/containers/nodocker ] || \
echo "Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg." >&2
exec podman "$@"
```

You can also go further and create a `docker.sock` with the following command:

```bash
sudo ln -s $HOME/.lima/podman/sock/podman.sock /var/run/docker.sock
```

## Bonus 2: easily switch between the Lima VM and `podman-machine-default`

If you want to quickly switch the connection between our newly created Lima VM and the `podman-machine-default` VM, you can create copy these 2 quick commands in your `.bashrc`/`.zshrc`:

```bash
# let podman connect with the lima VM
podman-use-lima() {
    podman system connection default podman
    sudo rm /var/run/docker.sock
    sudo ln -s $HOME/.lima/podman/sock/podman.sock /var/run/docker.sock
}

# let podman connect to the podman-machine-default-root VM (standard podman VM)
podman-use-default() {
    podman system connection default podman-machine-default-root
    sudo rm /var/run/docker.sock
    sudo ln -s $HOME/.local/share/containers/podman/machine/podman.sock /var/run/docker.sock
}
```

And then simply run in your bash `podman-use-lima` to use the lima VM, or `podman-use-default` to switch back to the default VM.

## Conclusion

In this blog we have covered how to quickly create a Lima VM that can be used with `podman`. The advantages of such VM can be manifold:

* much more customisable than the default VM coming with **Podman Desktop**;
    
* portable on multiple platforms;
    
* fully backward-compatible with `docker`.
