Giter Club home page Giter Club logo

vagrant-docker-provider's Introduction

Vagrant Docker Provider Image

License Docker Pulls

This repo will build a docker image that can be used as a provider for Vagrant as a Linux development environment.

The ready made Docker Hub image can be found here: rofrano/vagrant-provider:ubuntu

Why Vagrant with Docker?

This was inspired by Apple's introduction of the M1 chip which is ARM based. That means that solutions which use Vagrant and VirtualBox will not work on Apple M1 because VirtualBox requires an Intel processors. This lead me to find a solution for a virtual development environment that works with ARM and thus Apple M1 computers. You can find out more information about why I built it here:

Developing on Apple M1 Silicon with Virtual Environments

Docker has introduced Docker Desktop for Apple silicon that runs Docker on Macs that have the Apple M1 chip. By using Docker as a provisioner for Vagrant, we can simulate the same experience as developers using Vagrant with VirtualBox. This is one case where you actually do want a Docker container to behave like a VM.

Image Contents

The ubuntu image is based on Ubuntu 21.04 and the debian image is Debian 11. Both contain the packages that are needed for a valid vagrant box. This includes the vagrant userid with password-less sudo privileges. It also contains as sshd server. Normally, it is considered a bad idea to run an ssh daemon in a Docker container but in this case, the Docker container is emulating a Virtual Machine (VM) to provide a development environment so it makes perfect sense. ;-)

Example Vagrantfile

Here is a sample Vagrantfile that uses this image:

Vagrant.configure("2") do |config|
  config.vm.hostname = "ubuntu"

  config.vm.provider :docker do |docker, override|
    override.vm.box = nil
    docker.image = "rofrano/vagrant-provider:ubuntu"
    docker.remains_running = true
    docker.has_ssh = true
    docker.privileged = true
    docker.volumes = ["/sys/fs/cgroup:/sys/fs/cgroup:rw"]
    docker.create_args = ["--cgroupns=host"]
    # Uncomment to force arm64 for testing images on Intel
    # docker.create_args = ["--platform=linux/arm64"]     
  end  
end

Example: Docker in Docker

This image will also run docker in docker. To install docker using vagrant add this to the Vagrantfile:

  # Install Docker and pull an image
  config.vm.provision :docker do |d|
    d.pull_images "alpine:latest"
  end

This will install Docker and pull the alpine:latest image. You can pull and run any image you'd like.

Example: ARM64

If you want to test the ARM version on an Intel computer just uncomment the docker.create_args line which adds --platform=linux/arm64 to the arguments. This will add the --platform flag to the docker run command to force the aarch64 image to be used via qemu.

There is also a debian variant to this image that is based on debian:11. That can be used by changing the docker.image line above to use the rofrano/vagrant-provider:debian image instead like this:

    docker.image = "rofrano/vagrant-provider:debian"

Command Line Usage

To use this provider, add the --provider flag to your vagrant command:

vagrant up --provider=docker

This will use this the docker image specified in your Vagrantfile as the base box.

You can also run this using the provided Makefile with:

make run

Build Multi-Archtecture Image

To build this image you must use buildx and build it for multiple architectures so that it can run on both Intel and ARM machines.

Initialize builder

If you don't have a builder you must first create one:

% export DOCKER_BUILDKIT=1
% docker buildx create --use --name=qemu
qemu
% docker buildx inspect --bootstrap

The provided Makefile will do this for you with:

make init

This will initialize the buildx provider as above.

Building the default Ubuntu image

Then you can build the multi-platform image like this (where {account} is the name of your Docker Hub account):

docker buildx build --file Dockerfile.ubuntu --tag {account}/vagrant-provider:ubuntu --platform=linux/amd64,linux/arm64 --push .

This will use QEMU to build a multi-platform image and push it to docker hub.

You can also build your image with make:

make build REGISTRY={your account}

It is better if you set an environment varaible called REGISTRY and it will be picked up by make. For example, if your Docker Hub account name is foo you would use:

export REGISTRY=foo
make build

This will ensure that all of the make commands will use your registry and not mine (i.e., rofrano)

Building image variants

The default image is ubuntu but you can build the debian image by adding the argument IMAGE_TAG=debian like this:

make build IMAGE_TAG=debian

This will use the Dockerfile.debian and push to an image called rofrano/vagrant-provider:debian

If you want to add your own variant, just create a Dockerfile with the variant name as the extension and it will be picked up (e.g., Dockerfile.alpine). Then you can use make build IMAGE_TAG=alpine to build and push that image.

Remove the buildx instance

When not needed, you can safely stop and/or remove the buildx containers with the following commands:

docker buildx stop
docker buildx rm

This can also be accomplised with:

make remove

Credits

A huge thanks to Matthew Warman who provided the Dockerfile from mcwarman/vagrant-provider as the bases for my Dockerfile using systemd. He added all the magic to make it work and I am very greateful for his generosity.

vagrant-docker-provider's People

Contributors

jimmcslim avatar rofrano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vagrant-docker-provider's Issues

Docker container size

Hi John, Is it possible to provision a larger Vagrant docker container? The Vagrant notes on disk sizes (https://www.vagrantup.com/docs/disks/usage) seem to only apply to Virtual Box. I am using APFS on MacOS, and df showed that "overlay" on / (11G) was full during my build phase, so I need more temporary storage.

Multiple errors with vagrant up

I set up everything as the repo said, and I keep receiving this log errors:

    report: Need to get 31.9 MB of archives.
    report: After this operation, 244 kB disk space will be freed.
    report: Do you want to continue? [Y/n] Abort.
    report: E: gnupg, gnupg2 and gnupg1 do not seem to be installed, but one of them is required for this operation
    report: E: gnupg, gnupg2 and gnupg1 do not seem to be installed, but one of them is required for this operation
    report: deb http://apt.postgresql.org/pub/repos/apt/ jammy-pgdg main
    report: /tmp/vagrant-shell: line 7: deb: command not found
    report: sudo: apt-add-repository: command not found
    report: Hit:1 http://ports.ubuntu.com/ubuntu-ports jammy InRelease
    report: Get:2 http://apt.postgresql.org/pub/repos/apt jammy-pgdg InRelease [86.6 kB]`

thats just a few errors but I have tons of bugs after those

Help needed.

The documentation mentioned that instead of using docker, vagrant can also support docker-compose as a provider.

compose (boolean) - If true, Vagrant will use docker-compose to manage the lifecycle and configuration of containers. This defaults to false.
compose_configuration (Hash) - Configuration values used for populating the docker-compose.yml file. The value of this Hash is directly merged and written to the docker-compose.yml file allowing customization of non-services items like networks and volumes.

But maybe my understanding is incorrect, maybe it only means internally a docker-compose is used, but if one has multiple containers, they all have to be config-ed separately?
I'm confused and I can't find an example anywhere. You seemed to have looked into this, do you happen to know whether a docker-compose file can be used a provider?

If yes, can one do the following too?
use shell provisioner with the containers defined inside the docker-compose file. How to refer those containers by vagrant names?
enable ssh in the docker image;
use ansible provisoner with the containers defined inside the docker-compse file.
use the compose-configuration hash to merge with docker-compose file.

once again :default: Warning: Remote connection disconnect. Retrying... with with Ubuntu 23.04 and latest Docker 4.22

Hello,

sadly looks like the old issue discussed and resolved here: #5
returned again

I tried to build the imagine in this repo with Ubuntu 23.04 and latest Docker 4.22

and got

=> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Remote connection disconnect. Retrying...
default: Warning: Remote connection disconnect. Retrying...
default: Warning: Remote connection disconnect. Retrying...

any ideas why it happens this time around?

to replicate I used this Vagrantfile:


-- mode: ruby --

vi: set ft=ruby :

Vagrant.configure(2) do |config|
config.vm.hostname = "ubuntu"

############################################################

Provider for Docker on Intel or ARM (aarch64)

############################################################
config.vm.provider :docker do |docker, override|
override.vm.box = nil
#docker.image = "rofrano/vagrant-provider:ubuntu"
docker.build_dir = "."
docker.remains_running = true
docker.has_ssh = true
docker.privileged = true
docker.volumes = ["/sys/fs/cgroup:/sys/fs/cgroup:rw"]
docker.create_args = ["--cgroupns=host"]
# Uncomment to force arm64 for testing images on Intel
# docker.create_args = ["--platform=linux/arm64", "--cgroupns=host"]
end

Install Docker and pull an image

config.vm.provision :docker do |d|

d.pull_images "alpine:latest"


and Dockerfile with Ubuntu 23.04:


FROM ubuntu:23.04
LABEL MAINTAINER="John Rofrano [email protected]"

ENV DEBIAN_FRONTEND noninteractive

Install packages needed for SSH and interactive OS

RUN apt-get update &&
yes | unminimize &&
apt-get -y install
openssh-server
passwd
sudo
man-db
curl
wget
vim-tiny &&
apt-get -qq clean &&
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Enable systemd (from Matthew Warman's mcwarman/vagrant-provider)

RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in ; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done);
rm -f /lib/systemd/system/multi-user.target.wants/
;
rm -f /etc/systemd/system/.wants/;
rm -f /lib/systemd/system/local-fs.target.wants/;
rm -f /lib/systemd/system/sockets.target.wants/udev;
rm -f /lib/systemd/system/sockets.target.wants/initctl;
rm -f /lib/systemd/system/basic.target.wants/
;
rm -f /lib/systemd/system/anaconda.target.wants/*;

Enable ssh for vagrant

RUN systemctl enable ssh.service;
EXPOSE 22

Create the vagrant user

RUN useradd -m -G sudo -s /bin/bash vagrant &&
echo "vagrant:vagrant" | chpasswd &&
echo 'vagrant ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vagrant &&
chmod 440 /etc/sudoers.d/vagrant

Establish ssh keys for vagrant

RUN mkdir -p /home/vagrant/.ssh;
chmod 700 /home/vagrant/.ssh
ADD https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub /home/vagrant/.ssh/authorized_keys
RUN chmod 600 /home/vagrant/.ssh/authorized_keys;
chown -R vagrant:vagrant /home/vagrant/.ssh

Run the init daemon

VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]


Regards, Roman

Vagrantfile doesn't work when using Docker as the provider

I tried your 2 Vagrant files but none of them work in my Windows if I use Docker as the provider.

No issues if I use VirtualBox.

Can you help?

1st file

Vagrant.configure("2") do |config|
  config.vm.hostname = "ubuntu"

  config.vm.provider :docker do |docker, override|
    override.vm.box = nil
    docker.image = "rofrano/vagrant-provider:ubuntu"
    docker.remains_running = true
    docker.has_ssh = true
    docker.privileged = true
    docker.volumes = ["/sys/fs/cgroup:/sys/fs/cgroup:rw"]
    docker.create_args = ["--cgroupns=host"]
    # Uncomment to force arm64 for testing images on Intel
    # docker.create_args = ["--platform=linux/arm64"]     
  end  
end

2nd file

https://github.com/rofrano/vagrant-docker-provider/blob/master/Vagrantfile

Error messages -

c:\>vagrant up 
Bringing machine 'default' up with 'docker' provider...
==> default: Creating and configuring docker networks...
==> default: Vagrant has noticed that the synced folder definitions have change
==> default: With Docker, these synced folder changes won't take effect until y
==> default: destroy the container and recreate it.
==> default: Enabling network interfaces...
==> default: Starting container...
==> default: Waiting for container to enter "running" state...
The container started either never left the "stopped" state or
very quickly reverted to the "stopped" state. This is usually
because the container didn't execute a command that kept it running,
and usually indicates a misconfiguration.

If you meant for this container to not remain running, please
set the Docker provider configuration "remains_running" to "false":

  config.vm.provider "docker" do |d|
    d.remains_running = false
  end

I tried to add d.remains_running = true but still the same issues.

Thanks.

/dev/null: operation not permitted error

Hi! Trying this on M1 Mac, docker desktop 4.12.0

Sample vagrant file

  config.vm.hostname = "ubuntu"

  config.vm.provider :docker do |docker, override|
    override.vm.box = nil
    docker.image = "rofrano/vagrant-provider:ubuntu"
    docker.remains_running = true
    docker.has_ssh = true
    docker.privileged = true
    docker.volumes = ["/sys/fs/cgroup:/sys/fs/cgroup:rw"]
    docker.create_args = ["--cgroupns=host"]
  end

  config.vm.provision :docker do |d|
    d.pull_images "redis:6-alpine"
    d.run "redis:6-alpine",
      args: "-d --name redis -p 6379:6379 -v redis:/data"
  end
end

vagrant up -provider docker leads to

docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error reopening /dev/null inside container: open /dev/null: operation not permitted: unknown.

I can vagrant ssh into the box just fine.

default: Warning: Remote connection disconnect. Retrying...

Hey, in some reason, it doesn't work anymore.
It fails with this error:

vagrant up
Bringing machine 'default' up with 'docker' provider...
==> default: Creating and configuring docker networks...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Creating the container...
    default:   Name: vagrant-docker-provider-original_default_1639066115
    default:  Image: rofrano/vagrant-provider:ubuntu
    default: Volume: /sys/fs/cgroup:/sys/fs/cgroup:ro
    default: Volume: /Users/user/vagrant-docker-provider-original:/vagrant
    default:   Port: 127.0.0.1:2200:22
    default:
    default: Container created: fb5e8f8218b7cc31
==> default: Enabling network interfaces...
==> default: Starting container...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
^C==> default: Waiting for cleanup before exiting...

Laptop: MacBook Pro (14-inch, 2021)
OS: macOS Monterey 12.0.1
Docker version: 4.3.0 (71786)

When I log in with exec to container, I see that systemd isn't running.

docker exec -ti vagrant-docker-provider-original_default_1639066406 bash
root@ubuntu:/# ps auxwf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           7  2.0  0.0   3880  3044 pts/0    Ss   16:13   0:00 bash
root          16  0.0  0.0   5472  2312 pts/0    R+   16:13   0:00  \_ ps auxwf
root           1  0.4  0.0  17444  6816 ?        Ss   16:13   0:00 /usr/sbin/init
root@ubuntu:/# systemctl status
Failed to connect to bus: No such file or directory

I am looking for the solution but didn't find yet.
On Linux it works fine:

docker run --tmpfs /tmp --tmpfs /run -it -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 8081:80 -p 8080:8080 --name my_image <my_image>

@rofrano

dockerd cannot run inside the vagrant docker provider due to iptables

When provisioning the container on M1 in x86_64 mode, an error is received:

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

service docker start

Stdout from the command:


Stderr from the command:

Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xe" for details.

I jumped into the console and tried to run dockerd to see what the output was, and it was an issue with iptables being converted to nftables rather than legacy mode, and after updating iptables to use iptables-legacy:

update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

A different error is encountered: iptables v1.8.7 (legacy): can't initialize iptables table 'nat': iptables who? (do you need to insmod?)

As a result, it is impossible to provision docker containers inside the machine.

vagrant ssh doesn't connect using login shell?

Doesn't look like the contents of the vagrant user's .profile file are executed (ubuntu flavour), just .bashrc. My understanding is that vagrant ssh would connect using a login shell? Nor does .bash_profile get executed if I add one and logout/login. Same issue if I copy the output from vagrant ssh-config into my ~/.ssh/config file and attempt to connect that way.

Container take heavy space

hello firstly thank you for your work . it help me a lot . But i just noticed that running this image take more than 30% of my hard disk i don't know if it's coming from my vagrantfile or not

https://pastebin.com/Pwr5Kq1r

that is the link to my vagrantfile
Thank you for your help

Os information

Mac m1
Ram : 8go
Os Big sur

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.