Red Green Repeat Adventures of a Spec Driven Junkie

Migrating from Vagrant to Docker - Part 1

I have a new computer and well, the new computer does not run vagrant, well, it really doesn’t run virtual box, it does run docker. I have decided it’s time to go with docker for my virtualization needs.

I go over key commands in managing a vagrant system in my workflow: creating, running, and connecting into a guest operating system - and the docker equivalent.

If you are looking to migrate your workflow from vagrant to docker, you will gain a smoother path by knowing what vagrant commands map to docker commands to get the same things done.

This article will take you about five minutes to read.

James Bard - The Thomas Hunt and the America source and more information

Introduction

I enjoy working with a virtualbox when developing with vagrant managing the system configuration for me. The system is in a consistent state and

I am so comfortable in vagrant that if I want to get into docker more, I need the “docker equivalent for this vagrant command”.

The docker commands are around the base docker commands (i.e. docker (build | images | run | ps | exec)). Docker has additional tooling which I will explore deeper in the future.

This article will focus on the commands to get the current version of Ubuntu on vagrant and docker.

This article, part 1, will cover:

  • files for configuration
  • command to start system
  • command to login

Let’s get started!

Selecting Guest Operating System

With virtualized systems, one can run a different operating system than the current system, known as “guest” and “host”, respectively. Think: of a host providing resources for a guest to run.

How vagrant and docker specify which guest operating system is similar through specific configuration files.

Vagrantfile

The most basic Vagrantfile to have vagrant create a system using the current version Ubuntu as of this writing, it is: Focal Fossa would be:

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

Making this into one line is possible.

More Guest Operating Systems

If you want to find more operating systems, checkout vagrant boxes.

Dockerfile

The most basic Dockerfile that docker would accept to setup a system with Ubuntu Focal Fossal is:

FROM ubuntu:focal
CMD ["sleep", "1d"]

Why is line CMD ["sleep", "1d"] in the file? This line is optional as all it does is have the system sleep (for five days at that!)

This is one area where vagrant and docker differ philosophically.

From using it, vagrant, it is configuring a full blown guest system for usage within the host system. Remember, vagrant is an abstraction ontop of VirtualBox, which its core design goal is to emulate a computer inside a computer. (Vagrant just makes managing that computer easier.)

Docker core design goal is creating small “software appliances” that does one thing and one thing only (which I find ironic with software.)

Without the last line, CMD ["sleep", "1d"], the system would start and immediately shutdown, because the system finished all the commands. The sleep command here would keep the system up, for a day.

More Guest Operating Systems

For more guest operating systems in docker, checkout Docker Hub.

Creating System

Both vagrant and docker have simple ways to create the specified system from their respective configuration files.

vagrant

One would just have to run:

vagrant up

within the same folder as the Vagrantfile.

Vagrant creates all the associated files with it. Moving the Vagrantfile would create a new system, even with no file changes.

docker

The simplest command would be:

docker build .

which does work, I would suggest adding a <tag name>, such as: ubuntu or focal or ubuntu_focal or anything else.

docker build . -t <tag name specified by you>

To see what has been built, run: docker images:

REPOSITORY                TAG       IMAGE ID       CREATED        SIZE
<none>                    <none>    0fbb6d52aaba   33 hours ago   65.6MB
ubuntu_focal              latest    325acabf7223   33 hours ago   65.6MB

There are two images, one tagged: ubuntu_focal and the other without. Note, both are essentially Ubuntu Focal with slightly different build options.

docker and images

Docker designed to create lots of images and without tagged names, one would have only SHA and time to remember what image corresponds to which Dockerfile

Docker has a central repository for the images for the Dockerfile. Moving the Dockerfile will not create new system if there are no file changes.

Running System

After creating a system, getting a system running is the next step. This means starting the guest operating system within the host operating system, using up resources.

vagrant

This is where vagrant is convenient where the same command that creates the system vagrant up would also start the system.

docker

The command to running a system in docker created from the previous step is:

docker run <tag/SHA>

The <tag/image ID> refers to the listing output from docker images:

REPOSITORY                TAG       IMAGE ID       CREATED        SIZE
<none>                    <none>    0fbb6d52aaba   33 hours ago   65.6MB
ubuntu_focal              latest    325acabf7223   33 hours ago   65.6MB

When the image has a tag, that’s sufficient:

docker run ubuntu_focal

If only the Image ID is available:

docker run 0fbb

With those tag names and image IDs, the above commands are equivalent.

Logging In

The main use case I have virtualized software such as vagrant or docker is to run stuff inside those systems instead of on the host system. Logging into those systems with an interactive prompt is essential and simple.

vagrant

The command to login to a running system managed by vagrant:

vagrant ssh

vagrant has configured the virtual computer behind the scene with special SSH keys. It’s almost magical how simple working with a vagrant system is.

docker

Connecting to an interactive prompt on a docker system is a bit different as the design goal of docker is to have a software appliance.

Connecting to a running docker system will take:

  • finding the container ID of the system
  • running the docker exec command

docker ps

To find running containers, run: docker ps

$ docker ps
CONTAINER ID   IMAGE          COMMAND      CREATED          STATUS          PORTS   NAMES
98b09714e4d8   ubuntu_focal   "sleep 5d"   16 seconds ago   Up 15 seconds           suspicious_wescoff

The container ID here is: 98b0 OR suspcious_wescoff - you can use either to address the container in the docker exec command.

docker exec

The docker exec command is to execute a command in a running container. To get an interactive shell in a container:

docker exec -it <container ID/name> /bin/bash

Can I do Better?

There is a shortcut, if you only want to ever connect to the same container, use command:

docker ps | grep <tag> | awk '{ print $1 }'

To get the container ID of the image you want. Combine that with the previous command into:

docker exec -it $(docker ps | grep <tag> | awk '{ print $1 }') /bin/bash

This command is familiar :-)

Command Summary (so far)

Current summary of all the commands, side by side:

  vagrant docker
selecting guest operating system see Vagrantfile section see Dockerfile section
creating the system vagrant up docker build . -t <tag name>
running the system vagrant up docker run <tag>
connecting into the system vagrant ssh docker exec -it <container SHA> /bin/bash

Conclusion

A quick summary of different commands to migrate from managing virtual machines in vagrant to docker. Commands such as:

  • connecting into a system
  • running the system
  • creating it
  • selecting which guest operating system to run

I’m looking forward to sharing more as I migrate from having vagrant as the center of my workflow to docker.