Docker Terminal Windows



Today, 2021, anywhere you interview you for a Software Engineering position will probably be asked about Docker. You will be asked what it is, how it works, for what it is used, and how it is different/same to Kubernetes <– not covered here.

Installing Docker

First, how do we install Docker? https://www.docker.com/get-started. Download it for your favorite OS and install it. Docker runs at the OS level, so it does not require (too) much hardware in order to work correctly. That said, although Docker runs at the OS level and technically does not require Hyper-V, there are some components of Docker, especially on Windows, that will need Hyper-V ¯_(ツ)_/¯.

Start Docker when you log in - Automatically start Docker Desktop upon Windows system login. Expose daemon on tcp://localhost:2375 without TLS - Click this option to enable legacy clients to connect to the Docker daemon. You must use this option with caution as exposing the daemon without TLS can result in remote code execution attacks.

Once Docker is installed (I’m using 20.10.5 on Windows 10), you should be able to open a PowerShell or Cmd terminal or a Bash Terminal or whatever your favorite terminal is and simply run the command “docker” and get a long list of Cli Commands.

Docker

Congratulations, docker is intalled and running !

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. Docker Compose installs automatically with. Launch container: docker exec -it bash; Launch qtCreator: user@linuxkit-:$ qtcreator; Run: - new Powershell terminal. Launch container: docker exec -it bash; Launch nautilus: nautilus; Run: - new Powershell terminal. Launch container: docker exec -it bash; Launch terminal: user@linuxkit-:$.

Images

Once you have Docker successfully installed you’ll need to load an OS image of your choice so you can run your applications. Ubuntu is available by default, you can run a command to search for the name of the image and get back results

Pull Image

An image can be pulled from the default Docker registry or from a locally hosted location. For example, if you host a docker image repo locally such as https://mydockerrepo.com/ubuntu.18.04 or https://mydockerrepo.com/ubuntu.20.04

Docker does not need the http/https in the url path, it just uses namespaces to uniquely identify images once they are installed, so the names of the location or a tag are usually enough to help pull an image.

Pull Ubuntu 18.04 from Docker registry

Pull Ubuntu 18.04 from local Docker repo

Run

Docker is installed, you are able to pull docker images, what is next? The answer is run the image within an actual container. The image has been downloaded and can be seen by docker, running the docker images command will list the image:

The command to actually run the docker image within a container is docker run. But there are a few ways to run the image:

  • Attached
  • Detached
  • Named vs random name

Attached

Attached means that the current terminal will be “hi-jacked” when the container runs. You have the option to have interactive (-i) or non-interactive STDIN so that you can enter commands via the terminal. Ctrl-C or typing exit will cause the container to stop, you will not lose any data.

Running in attached mode is convenient when you want to be able to interact with the container directly from the terminal you use to run the container. You can start a process or perhaps update the container.

Again, the command to start a container in attached mode is one of two:

if your container is already running in detached mode (see below), you can attach to it by using this command:

Detached

Detached means that the container will run in the background, like a daemon. You can use ssh tools to interact with the container like a standard OS or simply attach to a detached container with the command docker attach [container name]

The command to start a container in detached mode is:

Named vs random name

When starting a container it is best practice to explictly name your container, otherwise docker will create a new container out of the image you are running with a random name. The random names docker choose are interesting and worth mentioning. Docker uses a verb and the name of a famous scientist (celebrity). Here are some sample names that docker comes up with :

  • hungry_cerf
  • relaxed_hofstadter
  • condescending_carver
  • gracious_brattain
  • cranky_villani
  • angry_gauss

If we start the same image without a name a few times without an explicte name provided we get random names. In our case docker generated agitated_johnson and strange_chaum. The command docker ps -a lists the docker containers with names.

If we wanted to relaunch a container that we exited, we could run with the name that was created:

A way to test that it is the same image (for santiy-check/learning purposes) is to create a container, create an empty file in a temp directory, then exit the container. Then exec back into the container by name and verify the file created still exists.

Changes

In the sanity-check example just above I mention creating a file, exiting the container, and then restarting the container. The file should still exist, and it does. But what other changes can we make to the container? There are many use-cases for this, perhaps we have a docker container that is running PiHole (https://pi-hole.net/) and we need to update PiHole or perhaps we wrote our own application that runs in a container that requires updating or perhaps we want to test running DotNet Core versions of our application and we need to install Dotnet Core.

Whatever the change, if we want to update a container we simply do so and then exit the container. The changes we make are kept until we remove the container.

Windows

Install Dot Net Core

I will use the default Ubuntu.1804 image from the Docker registry and install DotNet Core. This example is less about Docker, but will come into play in my next topic about “commits” or changing docker images.

First step is to verify that I can reach Microsoft’s servers. I’ll do that with a curl call and if I succeed, I want to add that Microsoft url to my sources.

This image is bare bones, we need to install curl.

Whoa! Lots of steps, but because this is a bare bones Ubuntu 18.04 image, there is very little pre-loaded. So I loaded curl, wget, updated package manager to know about Microsoft and finally installed dot net core 3.1.

Volumes

Now that we have dotnet core running, lets test that we can run a DotNet Core 3.1 application. The application is built on the host machine, then it needs to get into the container some how. That is one good use of Docker Volumes. Docker Volumes are similar to mounting devices (/mnt), but Volumes are Docker specific and therefore managed by Docker, not the container-OS.

The command to create a volume from host to container is -v [host_path]:[container_path]

On a Windows machine, this is how I share a directory @ C:dotnetcoreapp I tend to mount a volume:

Docker Terminal Windows 7

I have not had luck without using the double forward slashes on Windows to linux distro containers. It works, but if there is a better way, please leave me a comment below.

This code simply uses DotNet Core to determine if this is a Linux OS, and if so, output that the OS was detected as Linux:

Terminal

With this loaded interractively, I can now run the dotnet core app on the container:

Commit

As a developer, what I appreciate about Docker is that is resembles Git with its cli commands. For me, thinking about docker containers reminds me about source code. With Git we:

  • can pull code
  • change code
  • commit code
  • push code

We have pulled and changed the image by installing curl, wget, updating our apt sources, installing DotNet Core 3.1. That was a lot of work to getting our container to where we needed it to be in order to run our application. We do not to do that everytime we need to run our application on our Docker container.

We can commit all our changes and preserve the state of this container for future use. this is done with the Docekr commit command. First we retrieve the CONTAINER ID of our container. docker ps -a, followed by our commit.

This commit command indicates we want to commit the container with that specific CONTAINER ID with a new name, ubuntu.1804.dotnetcore3.1 and tag dotnetcore3.1. Now that we have commited it, this container will always run with all these changes. You will not need to reinstall any of the software bits.

Dockerfile

All the changes we made above are to an image we pulled from a fresh, clean, stable state. The Ubuntu image did not have wget or dotnet core installed. We installed those once we pulled the image. Another way to build an image is to use a Dockerfile. A dockerfile has a set of instructions that are followed by Docker to make changes to an existing image.

The same changes we made, could be done using a Dockerfile:

  • apt update – updated our package list
  • apt install curl – so we can make curl calls
  • apt install wget – so we download
  • apt install dotnet-sdk-3.1 – we installed dotnet core 3.1

This Dockerfile can be executed/loaded by docker using the following command:

This command will create a docker image using the docker hub image Ubuntu @ https://hub.docker.com/_/ubuntu

Once the command executes you should have a Docker image with Dot Net Core 3.1 installed. Now all you need to do is create a container from the image:

Issues on Windows

On my Windows 10×64 machine, I have an issue with Hyper-V being enabled and not being able to run VMWare side by side with Docker. I tend to have to run the following commands when loading VMWare and restarting my machine:

This enables Hyper-V and I can run VMWare and load snapshots.

When I need to run Docker, I tend to run the opposite command and restart my machine:

It is a bit cumbersome to have to restart over and over, but if I am working on Docker, I tend to not be working on VMWare and vice versa.

Conclusion

Open Terminal In Docker Container

Docker is awesome! I wanted to cover the basics of Docker, for myself and for anyone else who decides to start playing woti Docker. I look forward to more personal uses with Docker.

Windows Terminal Docker Container

Once you have installed Docker Toolbox, shortcut for Docker Quickstart Terminal would be created in the Start menu and Desktop.

Double click on the short cut to open Docker Terminal.

Docker Terminal

When you open Docker Terminal for the first time after Docker Toolbox installation, you may be prompted to give permission to create some components required for VirtualBox.

You can run docker commands in this terminal.

Let us try running hello-world application using the following command.

From the message echoed by Docker, we could observe that it has done some activities in the background to start hello-world application in Docker.

  1. The Docker client contacted the Docker daemon.
  2. The Docker daemon pulled the “hello-world” image from the Docker Hub. (amd64)
  3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.