- First Part – The basics: the basic principles of how container virtualization is implemented in Windows Server 2016 operating system.
- Second part – Up and Running: creating and managing Windows Server Containers using Docker.
- Third part – Into your Stride Working with Windows Containers and Docker
- Fourth part -- Save the Container Data
This is my latest article in this series about Windows Containers and Docker. I began writing this series one year ago, and since then there have been some great improvements. Before going deeper, I just want to describe the different versions of Docker that exist today in case you were not in the Docker ‘sphere’ or if you have just started using Docker. On March 2nd 2017, Docker changed their version format, and also changed the name of the Docker Engine package to either Docker Community Edition or Docker Enterprise Edition.
Installing Docker Community Edition on Windows 10
The first edition is called Docker Community Edition (CE). Docker (CE) is the new name for the free Docker products. Docker CE is compatible with the following OS Platform: Mac OS, Windows 10, Amazon AWS, Azure, CentOS, Debian, Fedora, and Ubuntu. On Top of that, Docker CE comes in two variants, Edge and Stable:
- Edge is for users wanting a drop of the latest and greatest features every month
- Stable is released quarterly and is for users that want an easier-to-maintain release pace
As Docker said, the Community Edition is great for developers and ops teams starting to build container apps. If you want to download this edition, go to the Docker Store. Once the download and installation are completed, you can run the package called Docker For Windows. At the time of writing this article, I installed Docker CE v18.03.
1 2 3 4 5 6 |
PS > Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V –All PS > Get-Service *docker* Status Name DisplayName ------ ---- ----------- Running com.docker.service Docker for Windows Service |
Confirm that you can run a simple container:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
PS > Docker run --rm -v c:/Users:/data alpine ls /data Unable to find image 'alpine:latest' locally latest: Pulling from library/alpine ff3a5c916c92: Pull complete Digest: sha256:7b848083f93822dd21b0a2f14a110bd99f6efb4b838d499df6d04a49d0debf8b Status: Downloaded newer image for alpine:latest All Users Default Default User Nicolas Public defaultuser0 desktop.ini |
If you work with Docker v18.03, then one of the main features is the ability to run both Windows and Linux images side by side, instead of having to switch Docker from Linux to Windows mode. Let’s confirm you are running the daemon in experimental mode:
1 2 3 |
PS > docker version -f '{{.Server.Experimental}}' True |
Or through the GUI:
Now, use the platform=linux parameter in Windows Container mode to run Linux images.
If you work with a previous version of Docker, it will run Linux containers by default. So, you must modify this setting and switch to Windows Container mode using either the Docker tray-menu:
or by running the following command in a PowerShell prompt
1 |
& $Env:ProgramFiles\Docker\Docker\DockerCli.exe –SwitchDaemon |
And that’s all. Docker CE is up and running on your Windows 10!
Now, you can go to the Docker Hub to find out which Container Images are available. For instance, you can run a simple Windows Container that contains PowerShell Core:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
PS > docker pull microsoft/powershell Using default tag: latest latest: Pulling from microsoft/powershell 1be7f2b886e8: Pull complete 6fbc4a21b806: Pull complete […] 74ebbb198c87: Pull complete Digest: sha256:38ac64ecec7e36b1868458b6b49e9d41332de56da2053c14830ef4915d909813 Status: Downloaded newer image for microsoft/powershell:latest PS > docker run --name PSCore -it microsoft/powershell PowerShell v6.0.1 Copyright (c) Microsoft Corporation. All rights reserved. https://aka.ms/pscore6-docs Type 'help' to get help. PS > $PSVersionTable Name Value ---- ----- PSVersion 6.0.1 PSEdition Core GitCommitId v6.0.1 OS Linux 4.9.75-linuxkit-aufs #1 SMP Tue Jan 9 10:58:17 UTC 2018 Platform Unix PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0 |
And you can very easily configure your Docker engine using the GUI Docker For Windows:
Installing Docker Enterprise Edition on Windows Server 2016
The second edition is called Docker Enterprise Edition (EE) and is a certified container platform for: CentOS, Red Hat Enterprise Linux (RHEL), Ubuntu, SUSE Linux Enterprise Server (SLES), Oracle Linux, Windows Server 2016, IBM Z, Amazon AWS, and Azure (Docker EE for Azure). Docker EE is available in three tiers: Basic, Standard and Advanced. Standard and Advanced tiers add advanced container management (Docker Datacenter) and Docker Security Scanning. You can find more information on the Docker Store about Docker EE and how to install it on other Operating Systems. In this case, you just need to run the following commands as administrator to install Docker EE on Windows Server 2016:
1 2 3 4 5 6 7 8 9 10 |
PS > Install-Module DockerProvider PS > Install-Package Docker -ProviderName DockerProvider -RequiredVersion preview -Force WARNING: A restart is required to enable the one or more features. Please restart your machine. Name Version Source Summary ---- ------- ------ ------- Docker 17.10.0-ee-pr... Docker Docker Enterprise Edition for Windows Server... PS > Restart-Computer |
As you may notice, the –Force parameter is used to install the very latest version of Docker EE. And then a restart of the Windows container Host is performed. This article will demonstrate using Docker EE v17.10 on Windows Server 2016.
Below is the release cycle for Docker in 2017. For example, v17.03 means that this release was released in March 2017.
Docker release cycle from the Docker website
To summarize, Docker CE has the same core features as Docker Enterprise Edition, so don’t be afraid, you can use Docker CE instead of Docker EE. Nonetheless, if you want to run Docker in production, I recommend installing at least Docker EE Basic.
Where’s My Data?
Imagine that you run a Windows Container and have some important data inside the container. Yes, containers are ephemeral, but you may want to save this data outside the container for many reasons. Well, you can easily share data between the Container Host and a Windows Container. Furthermore, you can also share data between two Windows Containers if you need to. This feature is very useful for Multi-Container Applications. For instance, applications need to share access to data or persist data after a container is deleted such as for databases or log files. This feature is called ‘Docker Volumes’.
In this section, I will describe how Docker Volumes work and explain four different ways to share data with containers:
- Creating an independent Docker Volume
- Sharing a Docker Volume with multiple containers
- Copying data from the Container Host to a container
- Creating a Docker Volume from a Dockerfile
When using Windows containers, it is still a good idea to use Docker Volumes to keep the data on the container host instead of on the container. You could also create multiple containers that will share the same Docker Volume. A Docker Volume will be visible both on the container host and on the container. The first thing to know is that Docker Volumes are stored in the following hidden path on the container host:
Note: Given that I will switch between the container host and containers, I will add a comment before each command.
Creating an Independent Docker Volume
To create a Docker Volume, type the following command:
1 2 3 4 |
#On the container host Docker volume create --name vol01 Vol01 |
To view all the existing Docker Volumes on the container host, type:
1 2 3 4 5 |
#On the container host PS > Docker volume ls DRIVER VOLUME NAME local vol01 |
Now you can attach the existing Docker Volume to a new container, iis01, using the –v parameter. The syntax is simple, you must specify the folder on the container host followed by the folder on the container:
1 2 |
#On the container host PS > Docker run --name iis01 -it -v C:\ProgramData\Docker\Volumes\Vol01:C:\Vol01 nanoserver/iis PowerShell |
By including the -it switch and specifying PowerShell, the current PowerShell console will be used to connect automatically to your container once it is created. If you want to exit from your container, type Exit and your container will be stopped. To leave the container running in background, use CTRL+P+Q. To open a new PowerShell session running in the container use Docker attach <container name> and press ENTER twice. When in a PowerShell session for an existing container, Exit will just switch back to the host but leave the container running. To start up a container use Docker start <container name>.
Now, create a simple text file on the container host:
Confirm that the file exists on the Container as well:
1 2 3 4 5 6 7 |
#On the iis01 container PS C:\> Get-ChildItem .\vol01\_data Directory: C:\vol01\_data Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/2/2018 8:49 PM 19 TestFile.txt |
In order to inspect the Container, run the following command and check the Mounts section:
1 2 |
#On the container host PS > Docker inspect iis01 |
Some of you are probably wondering if it’s possible to move the storage location? Fortunately, yes! To perform this task, you will need to create a configuration file called daemon.json:
1 2 3 4 5 6 7 |
#On the container host PS > New-Item -Type File -Path "C:\ProgramData\Docker\config" -Name daemon.json Directory: C:\ProgramData\Docker\config Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/2/2018 9:00 PM 0 daemon.json |
Then, provide the new storage location by adding this to the daemon.json file:
1 2 3 |
{ "data-root": "D:\\DockerVolumes" } |
Next, restart the Docker service. Create a new volume to confirm that the volume is created under the new Data Root folder:
1 2 3 |
#On the container host PS > Get-Service *Docker* | Restart-Service PS > Docker volume create --name newvolume |
The folder for the new Data Root folder will be created automatically. Be careful, older volumes are not moved automatically and existing containers and volumes will no longer be seen by Docker. Note that you can remove an existing Docker Volume using Docker volume rm <volume name>.
Sharing a Docker Volume with Multiple Containers
Start by creating a new Container called iis02 based on the nanoserver/iis image and attach a volume to it. Note that you don’t need to specify the Data Root folder because Docker will create the directory with a random folder name. Then create a file on the new volume.
1 2 3 4 5 6 7 8 9 10 11 12 |
#On the container host PS > Docker run -it --name iis02 --volume c:/vol03 nanoserver/iis powershell #On the "iis02" Container PS > "Welcome vol03" > .\vol03\vol03.txt PS > dir .\vol03 Directory: C:\vol03 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/3/2018 2:24 PM 32 vol03.txt |
Confirm that the file exists on the container host:
During the last step, you created a new Container and attached a new Docker Volume. Now, you will create a second Container called iis03 and attach the same Docker Volume C:/vol03 using the –volumes-from parameter:
1 2 |
#On the container host PS > docker run -it --name iis03 --volumes-from iis02 nanoserver/iis powershell |
Confirm that the volume is mounted. Create a new text file called vol03-from-iis03.txt:
1 2 3 4 5 6 7 8 9 10 11 12 |
#On the iis03 container PS C:\> dir .\vol03 Directory: C:\vol03 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/3/2018 2:24 PM 32 vol03.txt #The text file created on iis02 is visible on iis03 thanks to the "--volumes-from" parameter #On the "iis03" Container PS C:\> "Hello" > .\vol03\vol03-from-iis03.txt |
On the container host, both files are visible:
By default, access on a Docker Volume is in Read/Write mode. In some cases, you will need to limit access to the Docker Volume. You can set a volume as Read Only. Create a Container called db01 and attach a volume with Read Only (RO) access:
1 2 |
#On the container host PS > Docker run -it --name db01 --volumes-from iis02:ro nanoserver/iis powershell |
Now, try to create a file on this volume, but the task will fail:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#On the db01 container PS C:\> dir .\vol03 Directory: C:\vol03 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 3/3/2018 2:36 PM 16 vol03-from-iis03.txt -a---- 3/3/2018 2:24 PM 32 vol03.txt PS C:\> "Welcome" > .\vol03\vol03-from-db01.txt out-file : Access to the path 'C:\vol03\vol03-from-db01.txt' is denied. At line:1 char:1 + "Welcome" > .\vol03\vol03-from-db01.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OpenError: (:) [Out-File], UnauthorizedAccessException + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand |
Copying Data from the Container Host to a Container
Here is another interesting way to share data between the container host and a Windows Container. The Docker cp utility copies from the container’s file system to the container host or the reverse, from the container host to the Container. Create a new file, MyPackage.zip in the C:\Packages folder. Then copy the Zip file from the container host to the iis02 Container:
1 2 3 |
#On the container host PS > Docker cp C:\Packages\MyPackage.zip iis02:/inetpub PS > Docker attach iis02 |
The Docker Attach command will connect to the iis02 Container. Be careful, you must press ENTER twice to connect to your container. Check to see if the package exists in the Container:
Creating a Docker Volume from a DockerFile
You can mount a Docker Volume using a DockerFile. In the following example, you will create a nanoserver/iis image using the VOLUME keyword to mount a folder. Be sure to create the C:\Volume directory on the host if it doesn’t exist.
1 2 3 4 5 |
#On the container host PS > New-Item C:\Volume\Dockerfile -ItemType file PS > Add-Content -Path "C:\Volume\Dockerfile" -Value "FROM nanoserver/iis" PS > Add-Content -Path "C:\Volume\Dockerfile" -Value "VOLUME C:/Vol03" PS > Add-Content -Path "C:\Volume\Dockerfile" -Value "RUN powershell -Command gci" |
Navigate to the directory where this Dockerfile is located and run the following command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#On the container host PS C:\Volume> docker build -t volumeimg . Sending build context to Docker daemon 2.048kB Step 1/3 : FROM nanoserver/iis ---> 234e90a5d146 Step 2/3 : VOLUME C:/Vol03 ---> Using cache ---> 9acd2015fab2 Step 3/3 : RUN powershell -Command gci ---> Running in 98c4a64d54e2 Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 3/3/2018 4:37 PM inetpub d----- 3/3/2018 4:37 PM Program Files d----- 7/16/2016 12:09 PM Program Files (x86) d-r--- 3/3/2018 4:37 PM Users d----l 3/3/2018 4:37 PM vol03 d----- 3/3/2018 4:37 PM Windows -a---- 11/20/2016 11:32 AM 1894 License.txt […] Successfully tagged vol3:latest |
A custom Docker image has been created:
So now, every container created using this image will automatically mount the volume:
1 2 3 4 5 6 |
#On the container host PS > docker run --rm -it --name srv01 volumeimg powershell #On the "srv01" Container PS > cd vol03 PS C:\vol03> "Mount from Container" > mount.txt |
A new file called mount.txt has been successfully created on the container host. You can confirm the mount path with Docker inspect:
This method is very useful in DevOps mode or when you want to deploy multiple Windows Containers in bulk mode. The Volume will be mounted automatically during the deployment.
Linux Containers on Windows?
Another great improvement is Linux containers. You can now run Linux containers on a Windows container host. However, it can only be run in a dev/test environment because it is still in experimental version. So, what does it mean? Well, you will be able to deploy your Windows Containers Host, then install the Docker engine, and finally run a Linux container or a Windows container. Thanks to LinuxKit and the Moby Project, you can use Linux containers on Windows using one of the following Windows builds to support the feature:
- Windows 10 Fall Creators Update
- Windows Server 2016 1709 (new core edition)
In order to run Linux containers on Windows, Microsoft uses the Linux Containers on Windows (LCOW) feature. LCOW will use Hyper-V isolation, so you must install Hyper-V before using Linux containers:
1 2 |
#On the container host PS > Install-WindowsFeature Hyper-V -IncludeManagementTools -Restart |
Then the Docker daemon runs as a Windows process, and every time you start a Linux container, Docker launches a minimal Virtual Machine with a Linux kernel. However, the ‘VM’ is not user-visible in the Hyper-V console! It is still not possible to run Windows and Linux Docker containers side-by-side. It means that you must enable LCOW to run Linux containers, and disable LCOW to run Windows containers. If you work on Windows 10, please note that LCOW support is only available on the Edge channel.
Start by enabling the LCOW feature with the following commands.
1 2 3 |
#On the container host PS > [Environment]::SetEnvironmentVariable("LCOW_SUPPORTED", "1", "Machine") PS > Restart-Service Docker |
The feature has been enabled, so you can create a Linux container based on Ubuntu using the following command:
1 2 |
#On the contaner host PS > Docker run –it ubuntu |
At this step, you are running in the Ubuntu container on your Windows Server:
1 2 3 4 5 |
root@58e001fba499:/# pwd / root@58e001fba499:/# mkdir /tmp/Linux root@58e001fba499:/# ls /tmp linux |
To finish with a funny Linux container, you can run the NyanCat container:
1 2 |
#On the container host PS > Docker run -it supertest2014/nyan |
Conclusion
This article of the series discussed the new Docker versions that you can use depending your needs. The first one is Docker CE which is for development and testing environment, and the second one is Docker EE which is for production use. Then you saw:
- How to share data between the container host and a container.
- How to share data between two containers.
And to finish, you ran Linux containers on a Windows container host, which is a great improvement for sysadmin and developers. Currently, LCOW is still in beta and not supported In a production environment so please use it for dev purposes.
In the next article, I will discuss about how to manage and orchestrate our Windows containers with Kubernetes and Swarm.
Load comments