{"id":13903173,"url":"https://github.com/linka-cloud/d2vm","last_synced_at":"2025-05-16T13:02:48.895Z","repository":{"id":48009981,"uuid":"483227586","full_name":"linka-cloud/d2vm","owner":"linka-cloud","description":"Build Virtual Machine Image from Dockerfile or Docker image","archived":false,"fork":false,"pushed_at":"2025-04-29T14:16:37.000Z","size":16245,"stargazers_count":284,"open_issues_count":7,"forks_count":44,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-29T15:26:58.025Z","etag":null,"topics":["build","buildha","cloud","docker","dockerfile","go","golang","immutability","linux","nerctl","podman","qemu","virtualization"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linka-cloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-19T12:00:08.000Z","updated_at":"2025-04-27T12:58:26.000Z","dependencies_parsed_at":"2024-06-19T01:37:15.792Z","dependency_job_id":"5ee0ecd1-170f-423b-8eb8-5d4697cb1ffc","html_url":"https://github.com/linka-cloud/d2vm","commit_stats":{"total_commits":132,"total_committers":5,"mean_commits":26.4,"dds":"0.037878787878787845","last_synced_commit":"d8ee37833e25b22996adad2a0fe7026e24657e6b"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linka-cloud%2Fd2vm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linka-cloud%2Fd2vm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linka-cloud%2Fd2vm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linka-cloud%2Fd2vm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linka-cloud","download_url":"https://codeload.github.com/linka-cloud/d2vm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535792,"owners_count":22087397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","buildha","cloud","docker","dockerfile","go","golang","immutability","linux","nerctl","podman","qemu","virtualization"],"created_at":"2024-08-06T22:01:42.230Z","updated_at":"2025-05-16T13:02:48.872Z","avatar_url":"https://github.com/linka-cloud.png","language":"Go","readme":"\n# d2vm (Docker to Virtual Machine)\n\n[![Language: Go](https://img.shields.io/badge/lang-Go-6ad7e5.svg?style=flat-square\u0026logo=go)](https://golang.org/)\n[![Go Reference](https://pkg.go.dev/badge/go.linka.cloud/d2vm.svg)](https://pkg.go.dev/go.linka.cloud/d2vm)\n[![Chat](https://img.shields.io/badge/chat-matrix-blue.svg?style=flat-square\u0026logo=matrix)](https://matrix.to/#/#d2vm:linka.cloud)\n\n*Build virtual machine image from Docker images*\n\nThe project is heavily inspired by the [article](https://iximiuz.com/en/posts/from-docker-container-to-bootable-linux-disk-image/) and the work done by [iximiuz](https://github.com/iximiuz) on [docker-to-linux](https://github.com/iximiuz/docker-to-linux).\n\nMany thanks to him.\n\n**Status**: *alpha*\n\n[![asciicast](https://asciinema.org/a/520132.svg)](https://asciinema.org/a/520132)\n\n## Supported Environments:\n\n**Only building Linux Virtual Machine images is supported.**\n\nStarting from v0.1.0, **d2vm** automatically run build and convert commands inside Docker when not running on linux\nor when running without *root* privileges.\n\n*Note: windows should be working, but is totally untested.*\n\n## Supported VM Linux distributions:\n\nWorking and tested:\n\n- [x] Ubuntu (18.04+)\n  Luks support is available only on Ubuntu 20.04+\n- [x] Debian (stretch+)\n  Luks support is available only on Debian buster+\n- [x] Alpine\n- [x] CentOS (8+)\n\nUnsupported:\n\n- [ ] RHEL\n\nThe program uses the `/etc/os-release` file to discover the Linux distribution and install the Kernel,\nif the file is missing, the build cannot succeed.\n\nObviously, **Distroless** images are not supported.\n\n## Prerequisites\n\n### osx\n- [Docker](https://docs.docker.com/get-docker/)\n- [QEMU](https://www.qemu.org/download/#macos) (optional)\n- [VirtualBox](https://www.virtualbox.org/wiki/Downloads) (optional)\n\n### Linux\n- [Docker](https://docs.docker.com/get-docker/)\n- util-linux\n- udev\n- parted\n- e2fsprogs\n- dosfstools (when using fat32)\n- mount\n- tar\n- extlinux (when using syslinux)\n- qemu-utils\n- cryptsetup (when using LUKS)\n- [QEMU](https://www.qemu.org/download/#linux) (optional)\n- [VirtualBox](https://www.virtualbox.org/wiki/Linux_Downloads) (optional)\n\n#### sudo or root privileges\n\n*sudo* or root privileges are required for `d2vm` to performs operations that require root-level permissions, in particular:\n\n- mounting disk images and loopback devices requires [elevated privileges](https://linux.die.net/man/2/mount)\n- invoke `docker` commands, which require root-level permissions by default\n\n\n## Getting started\n\n### Install\n\n#### With Docker\n\n*Note: this will only work if both the source context (and Dockerfile) and the output directory are somewhere inside\nthe directory where you run the command.*\n\n```bash\ndocker pull linkacloud/d2vm:latest\nalias d2vm=\"docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock --privileged -v \\$PWD:/d2vm -w /d2vm linkacloud/d2vm:latest\"\n```\n\n```bash\nwhich d2vm\n\nd2vm: aliased to docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock --privileged -v $PWD:/d2vm -w /d2vm linkacloud/d2vm:latest\n```\n\n#### With Homebrew\n\n```bash\nbrew install linka-cloud/tap/d2vm\n```\n\n#### From release\n\nDownload the latest release for your platform from the [release page](https://github.com/linka-cloud/d2vm/releases/latest).\n\nExtract the tarball, then move the extracted *d2vm* binary to somewhere in your `$PATH` (`/usr/local/bin` for most users).\n\n```bash\nVERSION=$(git ls-remote --tags https://github.com/linka-cloud/d2vm |cut -d'/' -f 3|tail -n 1)\nOS=$(uname -s | tr '[:upper:]' '[:lower:]')\nARCH=$([ \"$(uname -m)\" = \"x86_64\" ] \u0026\u0026 echo \"amd64\" || echo \"arm64\")\ncurl -sL \"https://github.com/linka-cloud/d2vm/releases/download/${VERSION}/d2vm_${VERSION}_${OS}_${ARCH}.tar.gz\" | tar -xvz d2vm\nsudo mv d2vm /usr/local/bin/\n```\n\n#### From source\n\nClone the git repository:\n\n```bash\ngit clone https://github.com/linka-cloud/d2vm \u0026\u0026 cd d2vm\n```\n\nInstall using the *make*, *docker* and the Go tool chain:\n\n```bash\nmake install\n```\n\nThe *d2vm* binary is installed in the `$GOBIN` directory.\n\n```bash\nwhich d2vm\n\n/go/bin/d2vm\n```\n\n### Generate shell completion\n\nThe *d2vm* program supports shell completion for *bash*, *zsh* and *fish*.\n\nIt can be enabled by running the following command:\n\n```bash\nsource \u003c(d2vm completion $(basename $SHELL))\n```\n\nOr you can install the completion file in the shell completion directory by following the instructions:\n\n```bash\nd2vm completion $(basename $SHELL) --help\n```\n\n\n### Converting an existing Docker Image to VM image:\n\n```bash\nd2vm convert --help\n```\n```\nConvert Docker image to vm image\n\nUsage:\n  d2vm convert [docker image] [flags]\n\nFlags:\n      --append-to-cmdline string   Extra kernel cmdline arguments to append to the generated one\n      --boot-fs string             Filesystem to use for the boot partition, ext4 or fat32\n      --boot-size uint             Size of the boot partition in MB (default 100)\n      --bootloader string          Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64\n      --force                      Override output qcow2 image\n  -h, --help                       help for convert\n      --keep-cache                 Keep the images after the build\n      --luks-password string       Password to use for the LUKS encrypted root partition. If not set, the root partition will not be encrypted\n      --network-manager string     Network manager to use for the image: none, netplan, ifupdown\n  -o, --output string              The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default \"disk0.qcow2\")\n  -p, --password string            Optional root user password\n      --platform string            Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default \"linux/amd64\")\n      --pull                       Always pull docker image\n      --push                       Push the container disk image to the registry\n      --raw                        Just convert the container to virtual machine image without installing anything more\n  -s, --size string                The output image size (default \"10G\")\n      --split-boot                 Split the boot partition from the root partition\n  -t, --tag string                 Container disk Docker image tag\n\nGlobal Flags:\n      --time string   Enable formated timed output, valide formats: 'relative (rel | r)', 'full (f)' (default \"none\")\n  -v, --verbose       Enable Verbose output\n\n```\n\nCreate an image based on the **ubuntu** official image:\n\n```bash\nsudo d2vm convert ubuntu -o ubuntu.qcow2 -p MyP4Ssw0rd\n```\n```\nPulling image ubuntu\nInspecting image ubuntu\nNo network manager specified, using distribution defaults: netplan\nDocker image based on Ubuntu 22.04.1 LTS (Jammy Jellyfish)\nBuilding kernel enabled image\nCreating vm image\nCreating raw image\nMounting raw image\nCreating raw image file system\nCopying rootfs to raw image\nSetting up rootfs\nInstalling linux kernel\nUnmounting raw image\nWriting MBR\nConverting to qcow2\n```\n\nYou can now run your ubuntu image using the created `ubuntu.qcow2` image with **qemu**:\n\n```bash\nd2vm run qemu ubuntu.qcow2\n```\n```\nSeaBIOS (version 1.13.0-1ubuntu1.1)\n\n\niPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+BFF8C920+BFECC920 CA00\n\n\n\nBooting from Hard Disk...\n\nSYSLINUX 6.04 EDD 20191223 Copyright (C) 1994-2015 H. Peter Anvin et al\nNow booting the kernel from SYSLINUX...\nLoading /boot/vmlinuz... ok\nLoading /boot/initrd.img...ok\n[    0.000000] Linux version 5.4.0-109-generic (buildd@ubuntu) (gcc version 9)\n[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz ro root=UUID=b117d206-b8\n[    0.000000] KERNEL supported cpus:\n[    0.000000]   Intel GenuineIntel\n[    0.000000]   AMD AuthenticAMD\n[    0.000000]   Hygon HygonGenuine\n[    0.000000]   Centaur CentaurHauls\n[    0.000000]   zhaoxin   Shanghai\n\n...\n\nWelcome to Ubuntu 20.04.4 LTS!\n\n[    3.610631] systemd[1]: Set hostname to \u003clocalhost\u003e.\n[    3.838984] systemd[1]: Created slice system-getty.slice.\n[  OK  ] Created slice system-getty.slice.\n[    3.845038] systemd[1]: Created slice system-modprobe.slice.\n[  OK  ] Created slice system-modprobe.slice.\n[    3.852054] systemd[1]: Created slice system-serial\\x2dgetty.slice.\n[  OK  ] Created slice system-serial\\x2dgetty.slice.\n\n...\n\nUbuntu 20.04.4 LTS localhost ttyS0\n\nlocalhost login:\n```\n\nLog in using the *root* user and the password configured at build time.\n\n```\nlocalhost login: root\nPassword:\n\n\nWelcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-109-generic x86_64)\n\n * Documentation:  https://help.ubuntu.com\n * Management:     https://landscape.canonical.com\n * Support:        https://ubuntu.com/advantage\n\nThis system has been minimized by removing packages and content that are\nnot required on a system that users do not log into.\n\nTo restore this content, you can run the 'unminimize' command.\n\nThe programs included with the Ubuntu system are free software;\nthe exact distribution terms for each program are described in the\nindividual files in /usr/share/doc/*/copyright.\n\nUbuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by\napplicable law.\n\nroot@localhost:~#\n```\n\nType `poweroff` to shut down the vm.\n\n### Building a VM Image from a Dockerfile\n\nThe example directory contains very minimalistic examples:\n\n```bash\ncd examples\n```\n\n*ubuntu.Dockerfile* :\n\n```dockerfile\nFROM ubuntu\n\nRUN apt update \u0026\u0026 apt install -y openssh-server \u0026\u0026 \\\n    echo \"PermitRootLogin yes\" \u003e\u003e /etc/ssh/sshd_config\n\n```\n\nBuild the vm image:\n\nThe *build* command take most of its flags and arguments from the *docker build* command.\n\n```bash\nd2vm build --help\n```\n\n```\nBuild a vm image from Dockerfile\n\nUsage:\n  d2vm build [context directory] [flags]\n\nFlags:\n      --append-to-cmdline string   Extra kernel cmdline arguments to append to the generated one\n      --boot-fs string             Filesystem to use for the boot partition, ext4 or fat32\n      --boot-size uint             Size of the boot partition in MB (default 100)\n      --bootloader string          Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64\n      --build-arg stringArray      Set build-time variables\n  -f, --file string                Name of the Dockerfile\n      --force                      Override output qcow2 image\n  -h, --help                       help for build\n      --keep-cache                 Keep the images after the build\n      --luks-password string       Password to use for the LUKS encrypted root partition. If not set, the root partition will not be encrypted\n      --network-manager string     Network manager to use for the image: none, netplan, ifupdown\n  -o, --output string              The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default \"disk0.qcow2\")\n  -p, --password string            Optional root user password\n      --platform string            Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default \"linux/amd64\")\n      --pull                       Always pull docker image\n      --push                       Push the container disk image to the registry\n      --raw                        Just convert the container to virtual machine image without installing anything more\n  -s, --size string                The output image size (default \"10G\")\n      --split-boot                 Split the boot partition from the root partition\n  -t, --tag string                 Container disk Docker image tag\n\nGlobal Flags:\n      --time string   Enable formated timed output, valide formats: 'relative (rel | r)', 'full (f)' (default \"none\")\n  -v, --verbose       Enable Verbose output\n\n```\n\n```bash\nsudo d2vm build -p MyP4Ssw0rd -f ubuntu.Dockerfile -o ubuntu.qcow2 .\n```\n\nOr if you want to create a VirtualBox image:\n\n```bash\nsudo d2vm build -p MyP4Ssw0rd -f ubuntu.Dockerfile -o ubuntu.vdi .\n```\n\n### KubeVirt Container Disk Images\n\nUsing the `--tag` flag with the `build` and `convert` commands, you can create a\n[Container Disk Image](https://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/#containerdisk) for [KubeVirt](https://kubevirt.io/).\n\nThe `--push` flag will push the image to the registry.\n\n### Complete example\n\nA complete example setting up a ZSH workstation is available in the [examples/full](examples/full/README.md) directory.\n\n\n### Internal Dockerfile templates\n\nYou can find the Dockerfiles used to install the Kernel in the [templates](templates) directory.\n\n### TODO / Questions:\n\n- [ ] Create service from `ENTRYPOINT` `CMD` `WORKDIR` and `ENV` instructions ?\n- [ ] Inject Image `ENV` variables into `.bashrc` or other service environment file ?\n- [x] Use image layers to create *rootfs* instead of container ?\n\n### Acknowledgments\n\nThe *run* commands are adapted from [linuxkit](https://github.com/docker/linuxkit).\n","funding_links":[],"categories":["cloud"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinka-cloud%2Fd2vm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinka-cloud%2Fd2vm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinka-cloud%2Fd2vm/lists"}