Latest posts by Timothy Warner (see all)
- Using implicit PowerShell remoting to import remote modules - Thu, Mar 23 2017
- PowerShell remoting between Windows and Linux - Tue, Mar 21 2017
- ManageEngine Key Manager Plus - Track SSH keys and SSL certificates - Tue, Feb 28 2017
If you work with solution developers (also known as “programmers”) at your company, and especially if your teams adopt the DevOps methodology, then you’ve probably at least heard the phrase Docker containers.
I’ve written elsewhere here at 4sysops on Docker containers, and I suggest you read those pieces to gain some background knowledge on the technology. In a future article, I’ll teach you the same stuff, but using Windows PowerShell and the nifty Containers module.
Setting up our environment ^
In my opinion, the easiest and most portable way to start a container-enabled instance of Windows Server 2016 TP4 is to launch an Azure virtual machine. Frankly, Microsoft is so generous with Azure credit that there’s no excuse for any Windows systems administrator to have an Azure account.
I’ve covered deploying Azure virtual machines here at 4sysops; for our purpose, I’ll assume that we’ve deployed a VM using the Windows Server 2016 Core with Containers Tech Preview 4 template, as shown in the following screenshot:
Azure makes it convenient to deploy container-aware Windows Server instances.
I say that Azure is a “portable” solution because I can RDP into my cloud VM from Windows, OS X, or Linux. In case you’re interested, I use the official Microsoft Remote Desktop app on my Macs and rdesktop on my Linux computers.
You may be thinking, “Tim, why do you want to RDP into an Azure VM that’s running Server Core? All you have is a command prompt anyway. Can’t you open a remote tab in the Windows PowerShell ISE?”
Good question, indeed. We do need RDP in this case because the Windows Server containers we create will run in separate windows (technically cmd.exe or powershell.exe sessions), and that doesn’t work in the ISE, to the best of my knowledge.
Once you’re logged into your Windows Server 2016 Core RDP session, let’s verify that the Docker daemon’s running:
PS C:\> Get-Service -Name Docker
Status Name DisplayName
------ ---- -----------
Running Docker Docker Daemon
And as a quick sanity check, let’s retrieve the currently installed Docker version from within the PowerShell console:
PS C:\> docker --version
Docker version 1.10.0-dev, build 59a341e
Coolio! We’re ready to proceed.
Viewing images and creating a container ^
I have to stress to you how awesome an accomplishment it is on Microsoft’s and Docker’s parts that we have a native Docker runtime environment running in Windows Server 2016. This isn’t a hacky, Cygwin-dependent port—this is a code rewrite that gives us full Docker container functionality (including its robust command set), all from within Windows!
Recall that in Docker terminology, an image is analogous to a class in object-oriented programming. In other words, the image represents a blueprint for a containerized operating system, service, or application.
The Windows Server 2016 TP4 instance contains one prebuilt OS container mage that runs Windows Server 2016 Core itself; we use the command docker images to list Docker images:
PS C:\> docker images
REPOSITORY TAG IMAGE ID CREATED VSIZE
windowsservercore 10.0.10586.0 6801d964fda5 12 weeks ago 0 B
windowsservercore latest 6801d964fda5 12 weeks ago 0 B
I renamed the VIRTUAL SIZE property to VSIZE simply to get the output to line up properly for this article. A writer’s gotta do what a writer’s gotta do, you know? 😉
Although it looks like the VM has two pre-built Docker images, there’s really only one. You can verify this by inspecting the IMAGE ID property, which is a unique identifier for a given image. The difference is that we can reference the image either by the TAG identifier 10.0.10586.0 or by the more user-friendly TAG ID ‘latest.’
A container is an instance of a given image. We use the following Docker commands to list containers:
- docker ps (lists all running containers)
- docker ps –a (lists all containers, both started and stopped)
We use docker run to run a command in a new container. Here’s where containerization begins to shine—you can start Web servers, database servers, and app servers with a single statement and within seconds.
Here, of course, we’ll start a Windows Server 2016 Core container, and I’ll send the command powershell.exe so we’re in a PowerShell console on container start. First, I’ll show you the generic syntax:
docker run [OPTIONS] IMAGE [COMMAND]
Now, we’ll create a new container named ‘core1’ and start a PowerShell-based interactive session:
docker run -it --name core1 windowsservercore powershell.exe
The -it switch denotes an interactive (virtual console) session, by the way.
We’ll work with our newly generated container in a moment. First, I want to speak to you briefly about Docker documentation.
A few words about documentation ^
Remember that we’re not dealing with Windows PowerShell or even native Windows shell commands. Instead, we’re using native Docker commands that function identically regardless of whether our container host runs Windows, OS X, or Linux.
From your Windows Server 2016 container host, we use docker --help to list general syntax and all command names. To get command-specific help, use the following example to get you started:
PS C:\> docker attach --help
Usage: docker attach [OPTIONS] CONTAINER
Attach to a running container
--help=false Print usage
--no-stdin=false Do not attach STDIN
--sig-proxy=true Proxy all received signals to the process
For more robust Docker help, I suggest that you bookmark the official Docker Docs website. If you’re interested in a good “cheat sheet” recommendation, then check out the appropriately named Docker Cheat Sheet project at GitHub.
Working with a Windows Server container ^
Once you spawn a new container, Windows closes your current console and puts you in another one. The problem, and this is definitely where Microsoft has much work to do, is that it’s nearly impossible to know (a) whether you’re in a container or the container host operating system or (b) which container you’re in. Look at the following screenshot, which shows my Azure VM RDP session.
Who am I, where am I, and what am I doing here?
The only reason I know I’m inside my ‘core1’ container is that all the console output I had on my screen previously is gone and the on-screen text has a black background. That’s it. When I run hostname, I get the name of the VM container host. Very confusing! I’m sure that Microsoft will address this problem as they move along in their development.
To ‘detach’ from the container (technically called switching from interactive mode to daemon mode), we use the following wacky double key combination:
In my Azure VM’s PowerShell console, the prompt changed from C:\Windows\System32 back to C:\, which was my current working directory at the time I created the container.
Let’s verify that my ‘core1’ container is still running by using docker ps:
PS C:\> docker ps
CONTAINER ID IMAGE COMMAND NAMES
2da01ad71e36 windowsservercore "powershell.exe" core1
Regarding the previous output, I removed the CREATED, STATUS, and PORTS columns from my live output in the name of better legibility. So now we’re in the container host; how can we re-attach to our ‘core1’ container? Naturally, we use docker attach!
docker attach core1
…and, we’re back to the C:\Windows\System32 working directory and are ambiguously inside the ‘core1’ container. To gracefully stop the container, we’ll do the CTRL+P, CTRL+Q ‘salute’ to exit our interactive session, and then run docker stop:
docker stop core1
You should now find that docker ps reports no running Docker containers.
Let’s clean up. (This is, seemingly, already becoming a lost art in the Docker community.) We use docker rm to remove a container:
docker rm core1
Next steps ^
We’ve covered quite a bit of ground in this article, but we have so much more to accomplish! For instance, we haven’t (yet) learned how to build Windows Server containers. We’ll have to wait on the Windows Server team to implement that functionality, and then I’ll hopefully be the first to teach you how it works.
In the meantime, I hope that you’ll spend time getting your “sea legs” with Docker by using a fully fleshed-out implementation. For instance, consider building an Ubuntu Linux virtual machine instance by using Windows 8.1 or Windows 10 client Hyper-V. The Docker engine also runs great on OS X hosts. Docker even has a GUI front-end called Kitematic that simplifies container setup and management. Get this—Kitematic runs on Windows! That’s it for now—happy Dockering to you!