├── .github └── workflows │ └── lint.yml ├── podman-desktop └── readme.md /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | workflow_dispatch: 10 | 11 | jobs: 12 | check: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: azohra/shell-linter@v0.5.0 17 | -------------------------------------------------------------------------------- /podman-desktop: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | set -e 3 | 4 | show_help() { 5 | echo >&2 "podman-desktop 6 | 7 | --name virtual machine name 8 | --identity user ssh key 9 | ubuntu identifier (see multipass fetch) 10 | -- separator to pass options to `multipass launch` 11 | --cpus <#=1> # of cpus 12 | --mem amount of memeory 13 | --disk disk size 14 | --network see multipass launch --help 15 | " 16 | } 17 | 18 | die() { 19 | echo >&2 "$@" 20 | exit 1 21 | } 22 | 23 | install_cmd() { 24 | set +e 25 | if [ -z "$(command -v brew)" ]; then 26 | echo "# Install homebrew for easier MacOS management\n" 27 | # shellcheck disable=SC2016 28 | echo ' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"' 29 | fi 30 | set -e 31 | echo "brew install $1" 32 | } 33 | 34 | validate() { 35 | cmd=$1 36 | if [ ! -x "$(command -v "$cmd")" ]; then 37 | echo "ERROR: \`$cmd\` command not found. Please install $cmd." >&2 38 | echo "Instructions are:" 39 | install_cmd "$cmd" 40 | exit 1 41 | fi 42 | } 43 | 44 | validate "podman" 45 | validate "multipass" 46 | 47 | while [ $# -gt 0 ]; do 48 | key="$1" 49 | 50 | case $key in 51 | -h|--help) 52 | show_help; exit ;; 53 | -n|--name) 54 | INSTANCE_NAME="$2"; shift 2 ;; 55 | -i|--identity) 56 | IDENTITY="$2"; shift 2 ;; 57 | --) shift ; break ;; 58 | *) 59 | [ -n "$VERSION_ID" ] && die "already set version" 60 | VERSION_ID="$1"; shift ;; 61 | esac 62 | done 63 | 64 | INSTANCE_NAME="${INSTANCE_NAME:-podman}" 65 | IDENTITY="${IDENTITY:-$HOME/.ssh/podman}" 66 | PUBKEYFILE=${IDENTITY}.pub 67 | VERSION_ID="${VERSION_ID:-20.04}" 68 | MOUNTS=${MOUNTS-/Users /Volumes /private /tmp /var/folders} # Docker Desktop Defaults 69 | 70 | test -f "$IDENTITY" || die "cannot find identity $IDENTITY" 71 | test -f "$PUBKEYFILE" || die "cannot find pubkey $PUBKEYFILE" 72 | PUBKEY=$(cat "$PUBKEYFILE") 73 | 74 | PRIMARY=$(multipass get client.primary-name) 75 | if [ "$PRIMARY" != "$INSTANCE_NAME" ] && [ "$PRIMARY" != "primary" ]; then 76 | die "client.primary-name already set ($PRIMARY) for multipass" 77 | fi 78 | 79 | if ! pgrep multipassd 1>/dev/null 2>/dev/null; then 80 | echo multipassd not running, please run the following command and try again 81 | echo 82 | echo sudo launchctl start com.canonical.multipassd 83 | exit 1 84 | fi 85 | 86 | multipass set client.primary-name="$INSTANCE_NAME" 87 | echo >&2 "this may take a while - to view progress: 88 | 89 | multipass exec $INSTANCE_NAME -- tail -f /var/log/cloud-init-output.log 90 | " 91 | 92 | echo " 93 | users: 94 | - name: ubuntu 95 | ssh-authorized-keys: 96 | - ${PUBKEY} 97 | 98 | apt: 99 | preserve_sources_list: true 100 | sources: 101 | libcontainers.list: 102 | source: \"deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /\" 103 | keyid: 4D64390375060AA4 104 | 105 | package_upgrade: true 106 | packages: 107 | - podman 108 | - containerd 109 | - fuse-overlayfs 110 | 111 | write_files: 112 | - path: /lib/systemd/system/buildkitd.service 113 | owner: root:root 114 | permissions: \"0755\" 115 | content: | 116 | [Unit] 117 | Description=Buildkitd 118 | After=network.target 119 | 120 | [Service] 121 | Type=simple 122 | ExecStart=/opt/buildkit/bin/buildkitd --addr tcp://0.0.0.0:1234 123 | 124 | [Install] 125 | WantedBy=multi-user.target 126 | 127 | 128 | runcmd: 129 | - systemctl daemon-reload 130 | - mkdir /opt/buildkit 131 | - cd /opt/buildkit 132 | - curl -L https://github.com/moby/buildkit/releases/download/v0.9.3/buildkit-v0.9.3.linux-amd64.tar.gz > buildkit.tar.gz 133 | - tar -xvf buildkit.tar.gz 134 | - systemctl daemon-reload 135 | - sudo systemctl enable --now buildkitd.service 136 | - sudo systemctl start buildkitd.service 137 | " | multipass launch \ 138 | --name "${INSTANCE_NAME}" \ 139 | --cloud-init - \ 140 | "$@" \ 141 | "${VERSION_ID}" 142 | 143 | multipass exec "$INSTANCE_NAME" -- systemctl --user enable --now podman.socket 144 | multipass exec "$INSTANCE_NAME" -- sudo loginctl enable-linger ubuntu 145 | multipass exec "$INSTANCE_NAME" -- sudo systemctl enable --now ssh.service 146 | 147 | IP=$(multipass info "${INSTANCE_NAME}" | grep IPv4: | cut -d ':' -f2 | tr -ds ' ' '') 148 | CONNECTION=ssh://ubuntu@"${IP}"/run/user/1000/podman/podman.sock 149 | _IDENTITY=$(podman system connection list --format '{{.URI}} {{.Name}}' | grep "$CONNECTION" | cut -d' ' -f2) 150 | 151 | if [ "$_IDENTITY" ]; then echo "podman has a connection named $_IDENTITY"; else 152 | podman system connection add "$INSTANCE_NAME" --identity "${IDENTITY}" "$CONNECTION" 153 | fi 154 | 155 | for mount in $MOUNTS; do multipass mount "$mount" "$INSTANCE_NAME"; done 156 | 157 | printf "%s\n" "$INSTANCE_NAME" 158 | 159 | echo >&2 "You may want to add the following to your ~/.ssh/config: 160 | 161 | Host podman 162 | Hostname ${IP} 163 | User ubuntu 164 | " 165 | 166 | echo >&2 "To remove: 167 | 168 | podman system connection remove \"$INSTANCE_NAME\" 169 | multipass stop \"$INSTANCE_NAME\" 170 | multipass delete \"$INSTANCE_NAME\" 171 | multipass purge 172 | " 173 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # podman-desktop 2 | 3 | podman runs on linux, so this script spins up a virtual linux machine, and configures podman to use it as a remote host. 4 | 5 | Screen Shot 2021-09-03 at 11 22 37 AM 6 | 7 | Requires `muiltipass` and `podman` 8 | 9 | brew install multipass podman 10 | 11 | Setup a vm for podman. Values shown here are defaults. Mounts are the same as Docker Desktop. 12 | 13 | podman-desktop \ 14 | --name podman \ 15 | --identity ~/.ssh/podman \ 16 | 20.04 17 | 18 | If you'd like to pass any other params to `multipass launch`, just put them after `--` 19 | 20 | podman-desktop -- --cpus 3 --mem 3G --network 21 | 22 | By default, podman-desktop will mount the same folders as Docker Desktop. 23 | 24 | If you'd like to change the default mounts, set the `MOUNTS` variable to an array 25 | 26 | If you'd like to mount nothing, (for example, due to sshfs_server cpu usage) set `MOUNTS` to an empty string. 27 | 28 | 29 | ## Image building with buildkit 30 | 31 | Podman builds are considerably slower compared to Docker builds. One way to mitigate this is to use [buildkit](https://github.com/moby/buildkit). Multipass instances provisioned with podman-desktop already contain a ready-to-go buildkit daemon. All you need to do is use the buildkit-cli from your host system: 32 | 33 | buildctl \ 34 | --addr=tcp://$(shell multipass info podman --format json | jq -r ".info.podman.ipv4[]"):1234 \ 35 | build \ 36 | --frontend dockerfile.v0 \ 37 | --local context=. \ 38 | --local dockerfile=. \ 39 | --output type=oci,name="thisgetsignored:imagename" \ 40 | | podman load 41 | 42 | 43 | Please note, the resulting image will be `localhost/imagename:latest`, because [Buildkit does not seem write OCI compliant image annotations](https://github.com/containers/podman/issues/12560#issuecomment-990826349-permalink). 44 | 45 | 46 | # Thank you 47 | 48 | Thank you to @heussd for adding buildkit support 49 | --------------------------------------------------------------------------------