Chapter 10

Containers

Container concepts

Isolation modes

Managing containers with Docker

Managing containers

Applying updates

Container networking

Linux containers on Windows

Container orchestration

A container is a portable isolated application execution environment. Containers allow developers to bundle an application and its dependencies in a single image. This image can easily be exported, imported, and deployed on different container hosts, from a developer’s laptop computer, to Server Core on bare-metal hardware, and eventually to being hosted and run on Azure. Because an application’s dependencies are bundled with the application within a container, IT operations can deploy a container as soon as it is handed off without worrying whether an appropriate prerequisite software package has been installed or if a necessary setting has been configured. Because a container provides an isolated environment, a failure that occurs within one container will only impact that container and will not impact other containerized applications running on the container host.

Container concepts

Containers can be conceptually challenging. To understand how containers work, you first must understand some of the terminology involving containers. While these concepts will be fleshed out more completely later in this chapter, you should understand the following terms at a high level:

  • Container image. A container image is a template from which a container is generated. There are two general types of container images, which are usually created for a workload: a base OS image and a specific image. The difference between these containers on Windows Server is as follows:

    • Container base OS image. This is an image of the operating system upon which other container images are built. Four Windows OS container images are regularly published and updated by Microsoft. These images are available through an official public container registry.

    • Windows Server Core. This is an image of the Windows Server operating system in the Server Core configuration. Containers don’t run with a GUI, so Server with Desktop Experience is not available. This container image is suitable for traditional .NET Framework applications.

    • Nano Server. This is a Windows Server image with all unnecessary elements stripped out. It is suitable for hosting .NET Core applications. The Nano Server image container image is what became of the Nano Server installation option that was available with the RTM version of Windows Server 2016. Because the image is stripped down to the essentials, it is far smaller than the Windows Server Core image and can be deployed and run more quickly.

    • Windows IoT Core. This is an image for Internet of Things (IoT) applications.

    • Windows. This is an image that provides the full Windows API set but doesn’t include all the server roles and features that are available in the Server Core image. You should only use this option if the application you are trying to host has a dependency that is not included in the Windows Server Core container image.

    • Container image. A container image stores changes made to a running container base OS image or another container image. For example, you can start a new container from a container base OS image, make modifications such as installing Java or a Windows feature, and then save those modifications as a new container image. The new container image only stores the changes you make, and therefore, it is much smaller than the parent container base OS image. You can then create an additional container image that stores modifications made to the container image that has an installed Java and Windows feature. Each container image only stores the changes made to the image from which it was run.

  • Sandbox. The sandbox is the environment in which you can make modifications to an existing container image before you commit the changes to create a new container image. If you don’t commit those changes to a new image, those changes will be lost when the container is removed.

  • Image dependency. A new container image has the container image from which it was created as a dependency—for example, if you create a container image named WebServer-1.0 that has the IIS role installed from the Server Core base OS image, and the Server Core base OS image is a dependency for the WebServer-1.0 image. This dependency is very specific, and you can’t use an updated version of the Server Core base OS image as a replacement for the version that you used when creating the WebServer-1.0 image. You can then export this container image that only records the changes made to another container host. You can start the image as long as the dependency container OS base image is present on that container host. You can have multiple images in a dependency chain.

  • Container host. A container host is a computer that runs containers. A container host can be virtual, physical, or even a cloud-based Platform as a Service (PaaS) solution.

  • Container registries. Container registries are central storehouses of container images. While it’s possible to transfer containers or copy them to file shares using tools like FTP, common practice is to use a container registry as a repository for container images. Public container registries, such as the one that hosts Microsoft’s base OS images, also store previous versions of the container base OS images. This allows you to retrieve earlier versions of the container base OS image that other images may depend upon. Docker Hub is the primary public container registry used by Microsoft to publish images, though the container images themselves are hosted in the Microsoft Container Registry at mcr.microsoft.com. Container registries can be public or private. When working with your own organization’s container images, you have the option of creating and maintaining a private container registry.

Isolation modes

Windows Server supports two container isolation modes: Process Isolation mode and Hyper-V Isolation mode. In previous versions of Microsoft’s documentation, these isolation modes were occasionally called “Windows Server containers” and “Hyper-V containers.” Windows 10 supports only Hyper-V Isolation mode. Windows Server 2016 and Windows Server 2019 support Process Isolation and Hyper-V Isolation modes.

Process Isolation mode

Process Isolation mode provides a container with process and namespace isolation. Containers running in this Isolation mode share a kernel with all other containers running on the container host. This is similar to the manner in which containers run on Linux container hosts. Process Isolation is the default mode used when running a container. If you want to ensure that the container is being used, start the container using the --isolation=process option.

Hyper-V Isolation mode

A container running in Hyper-V Isolation mode runs in a highly optimized virtual machine that also provides an isolated application execution environment. Hyper-V Isolation mode containers don’t share the kernel with the container host, nor do they share the kernel with other containers on the same container host. You can only use Hyper-V Isolation mode containers if you have enabled the Hyper-V role on the container host. If the container host is a Hyper-V virtual machine, you will need to enable Nested Virtualization. By default, a container uses the Process Isolation mode. You can start a container in Hyper-V Isolation mode by using the --isolation=hyperv option.

For example, to create a Hyper-V container from the microsoft/windowsservercore image, issue this command:

Docker run -it --isolation=hyperv mcr.microsoft.com/windows/servercore cmd

Managing containers with Docker

Containers on Windows Server are managed using the Docker engine. The advantage is that the command syntax of Docker on Windows is almost identical to the command-line tools in Docker on Linux. While there is a community-maintained PowerShell module for managing containers on Windows Server available on GitHub, PowerShell is not the primary tool for Windows Server container management, and very few people use PowerShell to manage containers.

For Windows Server administrators unfamiliar with Docker syntax, the commands include extensive help support. Typing Docker at the command prompt will provide an overview of the high-level Docker functionality. You can learn more about specific commands by using the --help command parameter. For example, the following command will provide information about the Docker Image command:

docker image --help

Installing Docker

Docker is not included with the Windows Server installation media, and you don’t install it as a role or feature. Instead, you need to install Docker from the PowerShell Gallery. Although this is unusual for an important role on a Windows Server operating system, it does have the advantage of ensuring that you have the latest version of Docker.

The simplest way to install Docker is to ensure that your Windows Server computer has Internet connectivity. You then run the following command from an elevated PowerShell prompt, as shown in Figure 10-1, to install the Docker Microsoft Provider:

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
This is a screenshot shows the Install-Module command used to install Docker Microsoft Provider.

Figure 10-1 Install DockerMsftProvider

Next, install the most recent version of Docker. You do this by executing the following command, as shown in Figure 10-2; choose Yes when prompted to install software from a source not marked as Trusted.

Install-Package -Name docker -ProviderName DockerMsftProvider
This is a screenshot shows the command used to install Docker.

Figure 10-2 Install Docker

You’ll then need to restart the computer that will function as the container host to complete the installation of Docker. You can update the version of Docker when a new one becomes available by rerunning the following command:

Install-Package -Name docker -ProviderName DockerMsftProvider

Demon.json

If you want to change the default Docker Engine settings, such as whether to create a default NAT network, you need to create and configure the Docker Engine configuration file. This file doesn’t exist by default. When it is present, the settings in the file override the Docker Engine’s default settings.

You should create this file in the C:ProgramDataDockerconfig folder. Before editing the Demon.json file, you’ll need to stop the Docker service using the following command:

Stop-Service docker

You only need to add settings that you want to change to the configuration file. For example, if you only want to configure the Docker Engine to accept incoming connections on port 2701, you add the following lines to demon.json:

{
    "hosts": ["tcp://0.0.0.0:2701"]
}

The Windows Docker Engine doesn’t support all possible Docker configuration file options. The ones that you can configure are shown below:

{
    "authorization-plugins": [],
    "dns": [],
    "dns-opts": [],
    "dns-search": [],
    "exec-opts": [],
    "storage-driver": "",
    "storage-opts": [],
    "labels": [],
    "log-driver": "",
    "mtu": 0,
    "pidfile": "",

    "cluster-store": "",
    "cluster-advertise": "",
    "debug": true,
    "hosts": [],
    "log-level": "",
    "tlsverify": true,
    "tlscacert": "",
    "tlscert": "",
    "tlskey": "",
    "group": "",
    "default-ulimits": {},
    "bridge": "",
    "fixed-cidr": "",
    "raw-logs": false,
    "registry-mirrors": [],
    "insecure-registries": [],
    "disable-legacy-registry": false
}

These options allow you to do the following when starting the Docker Engine:

  • authorization-plugins. Which authorization plug-ins the Docker Engine should load

  • dns. Which DNS server the containers should use for name resolution

  • dns-opts. Which DNS options to use

  • dns-search. Which DNS search domains to use

  • exec-opts. Which runtime execution options to use

  • storage-driver. Specify the storage driver

  • storage-opts. Specify the storage driver options

  • labels. Docker Engine labels

  • log-driver. Default driver for the container logs

  • mtu. Container network MTU

  • pidfile. Path to use for daemon PID file

  • group. Specify the local security group that has permissions to run Docker commands

  • cluster-store. Cluster store options

  • cluster-advertise. Cluster address to advertise

  • debug. Enable Debug mode

  • hosts. Daemon sockets to connect to

  • log-level. Logging detail

  • Tlsverify. Use TLS and perform verification

  • tlscacert. Specify which Certificate Authorities to trust

  • tlscert. Location of the TLS certificate file

  • tlskey. Location of the TLS key file

  • group. UNIX socket group

  • default-ulimits. Default ulimits for containers

  • bridge. Attach containers to network bridge

  • fixed-cidr. IPv4 subnet for static IP address

  • raw-logs. Log format used

  • registry-mirrors. Preferred registry mirror

  • insecure-registries. Allow insecure registry communication

  • disable-legacy-registry. Block contacting legacy registries

Once you have made the necessary modifications to the daemon.json file, you should start the Docker service by running this PowerShell command:

Start-Service docker

Retrieving container OS image

You can retrieve the Server Core base OS container image by running the following command, as shown in Figure 10-3:

docker pull mcr.microsoft.com/windows/servercore:ltsc2019
This is a screenshot shows the output of the docker pull command.

Figure 10-3 Pull OS image

You can retrieve the Nano Server base OS container image by running this command:

docker pull mcr.microsoft.com/windows/nanoserver:1909

Unlike the Server Core image, where you will want to pull the Long Term Servicing Channel (LTSC) version, with Nano Server you’ll need to determine the most recent supported version, keeping in mind that Nano Server images are only supported for 18 months. You can do that by looking at the image page on Docker Hub at https://hub.docker.com/_/microsoft-windows-nanoserver.

The latest version of the Server Core image is updated frequently. Because of dependency issues when working with older containers, you might need an earlier version of the base OS image. To retrieve all versions of the WindowsServerCore image from the public registry, run this command:

docker pull -a mcr.microsoftcom/windows/servercore

To retrieve all versions of the Nano Server image, as shown in Figure 10-4, run this command:

Docker pull -a mcr.microsoft.com/windows/nanoserver
This screenshot shows the output of the docker pull -a command.

Figure 10-4 Pulling all versions of an OS image

Container registries and images

Container registries are repositories for the distribution of container images. The main container registry that will be of interest to Windows Server administrators is the Docker Hub public repository. Microsoft posts container images on the Docker Hub registry, including the base OS images, images that include evaluation editions of SQL Server, and technologies such as the latest builds of ASP.NET on containers and Azure CLI. You can view all Microsoft’s published container images at https://hub.docker.com/u/microsoft.

From the Docker Hub registry, you can retrieve the following published Microsoft container images:

  • Nanoserver. This is the base image for the Nano Server container operating system.

    docker pull mcr.microsoft.com/windows/nanoserver:1909
  • Windows Server Core. This is the base image for the Windows Server Core container operating system.

    docker pull mcr.microsoft.com/windows/servercore:ltsc2019
    docker pull mcr.microsoft.com/windows/servercore:1909
  • Windows IoT Core. This is the base image for Windows IoT containers.

    docker pull mcr.microsoft.com/windows/iotcore:1809
  • Windows IIS. This includes the Internet Information Services on Windows Server Core container operating system.

    docker pull mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
    docker pull mcr.microsoft.com/windows/servercore/iis:windowsservercore-1909
  • Microsoft SQL Server. This container image contains Microsoft SQL Server on Linux and will only run on Linux container hosts, rather than on Windows Server container hosts, unless you configure LCOW.

    docker pull mcr.microsoft.com/mssql/server:2019-latest
  • Azure Cli. This includes Azure CLI on a Linux container operating system.

    docker pull mcr.microsoft.com/azure-cli
  • ASP.NET Core Runtime. This includes ASP.NET Core on the Windows Server Core container operating system.

    docker pull mcr.microsoft.com/dotnet/core/aspnet:3.1
  • Microsoft PowerShell. This includes PowerShell on cross-platform container images.

    docker pull mcr.microsoft.com/powershell

In cases in which multiple images exist, such as Windows Server Core and Nano Server, you can use the -a option with the Docker pull command to retrieve all images. This can be helpful if you don’t know the image ID of the specific image that you wish to retrieve. For example, use this command when pulling the Microsoft PowerShell container image, which includes both Windows Server Core and Nano Server images: docker pull -a mcr.microsoft.com/powershell.

When you pull an image from a registry, the action will also download any dependency images that are required. For example, if you pull an image that was built on a specific version of the Windows Server Core base image and you don’t have that image on the container host, that image will also be downloaded from a container registry.

You can view a list of images that are installed on a Windows Server container host by using the following command:

Docker image list

You can use Windows Admin Center to view a list of container images that are installed on a Windows Server container host, as shown in Figure 10-5. You can also use Windows Admin Center to delete images that are installed on a Windows Server container host.

This screenshot shows a list of container images in Windows Admin Center.

Figure 10-5 List of container images

Managing containers

You use Docker to perform all container management tasks on computers running Windows Server. At present, the container management functionality available in Windows Admin Center is limited, but it’s likely that over time, most tasks that you can perform from the Docker prompt will be available in WAC.

Starting a container

You create a new container by specifying the container image from which you wish to create the container. You can start a container and run an interactive session either by specifying cmd.exe or PowerShell.exe by using the -it option with docker run. Interactive sessions allow you to directly interact with the container through the command line from the moment the container starts. Detached mode starts a container, but it doesn’t start an interactive session with that container.

For example, to start a container from the Microsoft/windowsservercore image and to enter an interactive PowerShell session within that container once it is started, use this command:

Docker run -it mcr.microsoft.com/windows/servercore:ltsc2019 powershell.exe

Also important is that, by default, containers use network address translation. This means that if you are running an application or service on the container that you want to expose to the network, you’ll need to configure port mapping between the container host’s network interface and the container. For example, you would run the following command if you had downloaded the Microsoft/iis container image and you wanted to start a container in Detached mode and map port 8080 on the container host to port 80 on the container (see Figure 10-6).

Docker run -d -p 8080:80 mcr.microsoft.com/windows/servercore/
iis:windowsservercore-ltsc2019
Port mapping in windows is shown.

Figure 10-6 Port mapping

This is only the very basic sort of information you’d need to get started with a container, and you will learn more about container networking later in this chapter.

You can verify which containers are running by using the docker ps command, as shown in Figure 10-7, or by using Windows Admin Center. The problem with the simple docker ps command option is that this will only show you the running containers and won’t show you any that are in a stopped state. You can see which containers are on a container host, including containers that aren’t currently running, by using the docker ps -a command.

This screenshot shows a list of containers generated by the docker ps command.

Figure 10-7 Listing containers

You can also view the containers that are on a Windows Server container host using Windows Admin Center, if you have loaded the Containers extension, as shown in Figure 10-8.

A screenshot of the windows admin center showing the details of containers.

Figure 10-8 Windows Admin Center container list

One thing that you’ll notice about containers is that they appear to be assigned random names, such as sarcastic_hedgehog, dyspeptic_hamster, and sententious_muppet. Docker assigns random names, rather than asking you for one, because containers are a more ephemeral type of application host than a VM; because they are likely to only have a short lifespan, it isn’t worth assigning any name that you’d need to remember. The reason for the structure of the random names is that they are easy to remember in the short term, which makes containers that you must interact with on a short-term basis easier to address than when using hexadecimal container IDs. Figure 10-9 shows the output of the docker ps -a command and shows the names of containers including: charming_gates, infallible_borg, frosty_lumiere, modest_kare, and dazzling_alemida.

This screenshot shows the output of the docker ps -a command.

Figure 10-9 List all images

Earlier in the chapter, you learned that it was possible to start a container in Detached mode. If you want to start an interactive session on a container that you started in Detached mode, use the docker exec -i <containername> powershell.exe command. Figure 10-10 shows entering an interactive session on a container started in Detached mode. The hostname command displays the container’s ID.

This screenshot shows starting an interactive session with the docker exec command.

Figure 10-10 Starting an interactive session

In some cases, it will be necessary to start a stopped container. You can start a stopped container using the Docker start <containername> command.

Modifying a running container

Once you have a container running, you can enter the container and make the modifications that you want to make to ensure that the application the container hosts will run correctly. This might involve creating directories, using the dism.exe command to add roles, or using the wget PowerShell alias to download and install binaries such as Java. For example, the following code, when run from inside a container, downloads and installs an older version of Java into a container based on the Server Core base OS container:

wget -Uri "http://javadl.sun.com/webapps/download/AutoDL?BundleId=107944" -outfile javaInstall.exe -UseBasicParsing
REG ADD HKLMSoftwarePoliciesMicrosoftWindowsInstaller /v DisableRollback /t REG_DWORD /d 1 | Out-Null ./javaInstall.exe /s INSTALLDIR=C:Java REBOOT=Disable | Out-Null

Once you are finished modifying the container, you can type Exit to exit the container. A container must be in a shut-down state before you can capture it as a container image. You use the docker stop <containername> cmdlet to shut down a container.

Creating a new image from a container

Once the container is in the desired state and shut down, you can capture the container to a new container image. You do this using the docker commit <container_name> <new_image_name> command. Figure 10-11 shows committing a modified container to a new container image named new_iis_java and verifying the properties of the image using the docker images command.

A screenshot shows the output of the docker commit command.

Figure 10-11 Docker commit

Once you have committed a container to a container image, you can remove the container using the docker rm command. For example, to remove the elegant_spence container, issue this command:

Docker rm elegant_spence

Using Dockerfiles

Dockerfiles are text files that allow you to automate the process of creating new container images. You use a Dockerfile with the docker build command to automate container creation, which is very useful when you need to create new container images from regularly updated base OS container images.

Dockerfiles have the elements shown in Table 10-1.

Table 10-1 Dockerfile Element

Instruction

Description

FROM

Specifies the container image used in creating the new image creation. For example:
FROM mcr.microsoftcom/windows/servercore:ltsc2019

RUN

Specifies commands to be run and captures them into the new container image.
For example:
RUN wget -Uri "http://javadl.sun.com/webapps/download/AutoDL?BundleId=107944" -outfile javaInstall.exe -UseBasicParsing
RUN REG ADD HKLMSoftwarePoliciesMicrosoftWindowsInstaller /v DisableRollback /t REG_DWORD /d 1 | Out-Null
RUN ./javaInstall.exe /s INSTALLDIR=C:Java REBOOT=Disable | Out-Null

COPY

Copies files and directories from the container host filesystem to the filesystem of the container. For windows containers, the destination format must use forward slashes. For example:
COPY example1.txt c:/temp/

ADD

Can be used to add files from a remote source, such as a URL. For example: ADD https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe

WORKDIR

Specifies a working directory for the RUN and CMD instructions.

CMD

A command to be run when deploying an instance of the container image.

For example, the following Dockerfile will create a new container from the mcr.microsoft.com/windows/servercore:ltsc2019 image, create a directory named ExampleDirectory, and then install the IIS Webserver feature.

FROM mcr.microsoftcom/windows/servercore:ltsc2019
RUN mkdir ExampleDirectory
RUN dism.exe /online /enable-feature /all /featurename:iis-webserver /NoRestart

To create a container image named example_image, change into the directory that hosts the Dockerfile (no extension) file and run the following command:

Docker build -t example_image

Managing container images

To save a Docker image for transfer to another computer, use the docker save command. When you save a Docker image, you save it in .tar format. Figure 10-12 shows exporting the new_iis_java image to the c:archive ew_iis_java.tar file.

This screenshot shows the output of the docker save command.

Figure 10-12 Docker save command

You can load a Docker image from a saved image using the docker load command. For example, Figure 10-13 shows loading a container image from the c:archive ew_iis_java.tar file created earlier.

This screenshot shows the output of the docker load command.

Figure 10-13 Load archived image

When you have multiple container images that have the same name, you can remove an image by using the image ID. You can determine the image ID by running the docker images command, as shown in Figure 10-14. You can also use Windows Admin Center to view this information. You can’t remove a container image until the last container created from that image has been deleted either directly or indirectly.

This screenshot shows the output of the docker images command.

Figure 10-14 Image list

You then remove the image by using the docker rmi command with the image ID. For example, Figure 10-15 shows the removal of the image with the ID a896e5590871 using this command:

docker rmi a896e5590871
This screenshot shows the output of the docker rmi command.

Figure 10-15 Remove image

You can also remove a container image by selecting the image in the list of containers in Windows Admin Center and clicking Delete.

Service accounts for Windows containers

Although containers based on the Server Core and Nano Server operating systems have most of the same characteristics as a virtual machine or a bare-metal deployment of the Server Core or Nano Server versions of Windows Server, one thing that you can’t do with containers is to join them to a domain. This is because containers are supposed to be temporary, rather than permanent, and domain-joining them would clog up Active Directory with unnecessary computer accounts.

While containers can’t be domain-joined, it is possible to use a group-managed service account (gMSA) to provide one or more containers with a domain identity similar to that used by a device that is realm-joined. Performing this task requires downloading the Windows Server Container Tools and ensuring that the container host is a member of the domain that hosts the gMSA. When you perform this procedure, the container’s LocalSystem and Network Service accounts use the gMSA. This gives the container the identity represented by the gMSA.

To configure gMSA association with a container, perform the following steps:

  1. Ensure that the Windows Server container host is domain-joined.

  2. Add the container host to a specially created domain security group. This domain security group can have any name.

  3. Create a gMSA and grant gMSA permission to the specially created domain security group of which the container host is a member.

  4. Install the gMSA on the container host.

  5. Use the New-CredentialSpec cmdlet on the container host to generate the gMSA credentials in a file in JSON format. This cmdlet is located in the CredentialSpec PowerShell module, which is available as a part of the Windows Server Container tools. For example, if you created a gMSA named MelbourneAlpha, you would run the following command:

    New-CredentialSpace -Name MelbourneAlpha -AccountName MelbourneAlpha
  6. You can verify that the credentials have been saved in JSON format by running the Get-CredentialSpec cmdlet. By default, credentials are stored in the C:ProgramDataDockerCredentialSpecs folder.

  7. Start the container using the --security-opt “credentialspec=” option and specify the JSON file containing the credentials associated with the gMSA. For example, run the following command if the credentials are stored in the file twt_webapp01.json:

    docker run --security-opt "credentialspec=file://twt_webapp01.json" --hostname
    webapp01 -it mcr.microsoft.com/windows/servercore:ltsc2019 powershell

Once you’ve configured the container to indirectly use the gMSA for its Local System and Network Service accounts, you can provide the container with permissions to access domain resources by providing access to the gMSA. For example, if you wanted to provide the container with access to the contents of a file share hosted on a domain member, you can configure permissions so that the gMSA has access to the file share.

Applying updates

One of the concepts that many IT operations personnel find challenging is that you don’t update a container that is deployed in production. Instead, you create a fresh container from the original container image, update that container, and then save that updated container as a new container image. You then remove the container in production and deploy a new container to production that is based on the newly updated image.

For example, you have a container that hosts a web app deployed from a container image named WebApp1 that is deployed in production. The developers in your organization release an update to WebApp1 that involves changing some existing settings. Rather than modifying the container in production, you start another container from the WebApp1 image, modify the settings, and then create a new container image named WebApp2. You then deploy a new container into production from the WebApp2 container image and remove the original un-updated container.

While you can manually update your container base OS images by applying software updates, Microsoft releases updated versions of the container base images each time a new software update is released. Once a new container OS base image is released, you or your organization’s developers should update existing images that are dependent on the container OS base image. Regularly updated container base OS images provide an excellent reason for eventually moving toward using Dockerfiles to automate the process of building containers. If you have a Dockerfile configured for each container image used in your organization, updating your Container base OS images when a new Container base OS image is released is a quick, painless, and automated process.

Container networking

Each container has a virtual network adapter. This virtual network adapter connects to a virtual switch, through which inbound and outbound traffic is sent. Networking modes determine how network adapters function in terms of IP addressing—meaning whether they use NAT or are connected to the same network as the container host.

Windows Containers support the following networking modes:

  • NAT. Each container is assigned an IP address from the private 172.16.0.0 /12 address range. When using NAT, you can configure port forwarding from the container host to the container endpoint. If you create a container without specifying a network, the container will use the default NAT network. The Docker service creates its own default NAT network. When the container host reboots, the NAT network will not be created until the Docker service has restarted. Any container that was attached to the existing NAT network and that is configured to persist after reboot (for example, because it uses the –restart always option) will reattach to the NAT network that is newly created when the Docker service restarts.

  • Transparent. Each container endpoint connects to the physical network. The containers can have IP addresses assigned statically or through DHCP.

  • Overlay. Use this mode when you have configured the Docker Engine to run in Swarm mode. Overlay mode allows container endpoints to be connected across multiple container hosts.

  • L2 Bridge. Container endpoints are on the same IP subnet used by the container host. IP addresses must be assigned statically. All containers on the container host have the same MAC address.

  • L2 Tunnel. This mode is only used when you deploy containers in Azure.

You can list available networks using the following command, as shown in Figure 10-16:

docker network ls
This screenshot shows the output of the docker network ls command. Two networks are shown.

Figure 10-16 Network list

You can also view a list of container networks in Windows Admin Center, as shown in Figure 10-17.

A screenshot of the windows admin center showing the details of containers.

Figure 10-17 Windows Admin Center network list

To view which containers are connected to a specific network, run this command:

Docker network inspect <network name>

You can create multiple container networks on a container host, but you need to keep in mind the following limitations:

  • If you are creating multiple networks of the transparent or L2 bridge type, you need to ensure that each network has a separate network adapter.

  • If you create multiple NAT networks on a container host, additional NAT network prefixes will be partitioned from the container host’s NAT network’s address space. (By default, this is 172.16.0.0/12.) For example, these will be 172.16.1.0/24, 172.16.2.0/24, and so on.

NAT

Network Address Translation (NAT) allows each container to be assigned an address in a private address space, while connecting to the container host’s network uses the container host’s IP address. The default NAT address range for containers is 172.16.0.0 /16. If the container host’s IP address is in the 172.16.0.0 /12 range, you will need to alter the NAT IP prefix. You can do this by performing the following steps:

  1. Stop the Docker service.

  2. Remove any existing NAT networks using the following command:

    Get-ContainerNetwork | Remove-ContainerNetwork
  3. Perform one of the following actions:

    • Edit the daemon.json file and configure the “fixed-cidr”:”< IP Prefix > /Mask” option to the desired network address prefix.

    • Edit the daemon.json file and set the “bridge”: “none” option, and then use the docker network create -d command to create a network. For example, use the following command to create a network that uses the 192.168.15.0/24 range, the default gateway of 192.168.15.1, and is named CustomNat:

      Docker network create -d nat --subnet=192.168.15.0/24 --gateway=192.168.15.1
      CustomNat
  4. Start the Docker service.

You can also allow connections to custom NAT networks when a container is run by allowing the use of the --Network parameter and specifying the custom NAT network name. To do this, you need to have the “bridge: none” option specified in the daemon.json file. Use the following command to run a container and join it to the CustomNat network created earlier:

Docker run -it --network=CustomNat <ContainerImage> <cmd>

Port mappings allow ports on the container host to be mapped to ports on the container. For example, use the following command to create the container to map port 8080 on the container host to port 80 on a new container created from the windowsservercore image and to run powershell.exe interactively on the container:

Docker run -it -p 8080:80 microsoft/windowsservercore powershell.exe

Port mappings must be specified when the container is created or when it is in a stopped state. You can specify them using the -p parameter or the expose command in a Dockerfile when using the -p parameter. A random port will be assigned if you do not specify a port on the container host, but you do specify one on the container itself. For example, run this command:

Docker run -itd -p 80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-
ltsc2019 powershell.exe

A random port on the container host can be mapped through to port 80 on the container. You can determine which port is randomly assigned using the docker ps command. Figure 10-18 shows a container named youthful_hopper that has had the port 54742 on the container host assigned to port 80 on the container.

A screenshot shows the output of the docker ps command. The port assigned to port 80 is displayed.

Figure 10-18 docker ps command

When you configure port mapping, firewall rules on the container host will be created automatically that will allow traffic through.

Transparent

Transparent networks allow each container endpoint to connect to the same network as the container host. You can use the Transparent Networking mode by creating a container network that has the driver name transparent. The driver name is specified with the -d option. Use this command:

docker network create -d transparent TransparentNetworkName

If the container host is a virtual machine running on a Hyper-V host, and you want to use DHCP for IP address assignment, it’s necessary to enable MACAddressSpoofing on the VM network adapter, as shown in Figure 10-19. The Transparent Network mode supports IPv6. If you are using the Transparent Network mode, you can use a DHCPv6 server to assign IPv6 addresses to containers.

A screenshot shows the Settings dialog box of a virtual machine. Advanced Features is selected; also, Enable MAC Address Spoofing is selected.

Figure 10-19 Enabling MAC address spoofing

If you want to manually assign IP addresses to containers, you must specify the subnet and gateway parameters when you create the transparent network. These network properties need to match the network settings of the network to which the container host is connected.

For example, let’s say your container host is connected to a network that uses the 192.168.30.0/24 network and uses 192.168.30.1 as the default gateway. Run this command to create a transparent network that will allow static address assignment for containers on this network called TransNet:

Docker network create -d transparent --subnet=192.168.30.0/24 --gateway=192.168.30.1
TransNet

Once the transparent network is created with the appropriate settings, you can specify an IP address for a container using the --ip option. For example, to start a new container from the microsoft/windowsservercore image, enter the command prompt within the container. Run this command to assign it the IP address 192.168.30.101 on the TransNet network:

Docker run -it --network:TransNet --ip 192.168.30.101 microsoft/windowsservercore cmd.exe

Just like when you use a transparent network, containers are connected directly to the container host’s network; you don’t need to configure port mapping into the container.

Overlay

You can only use Overlay Networking mode if the Docker host is running in Swarm mode as a Manager node. Each overlay network you create on a swarm cluster has its own IP subnet defined by an IP address prefix in the private address space. You create an overlay network by specifying overlay as the driver. For example, you can create an overlay network for the subnet 192.168.50.0/24 with the name OverlayNet by running the following command from a Swarm Manager node:

docker network create --driver=overlay –subnet=192.168.50.0/24 OverlayNet

Layer 2 Bridge

Layer 2 Bridge (L2 Bridge) networks are similar to transparent networks in that they allow containers to have IP addresses on the same subnets as the container host. Layer 2 Bridge networks differ in that IP addresses must be assigned statically; this is because all containers on the container host that use an L2 Bridge network have the same MAC address.

When creating an L2 Bridge network, you must specify the network type as l2bridge. You must also specify subnet and default gateway settings that matches the subnet and default gateway settings of the container host. For example, use the following command to create an L2 Bridge network named L2BridgeNet for the IP address range 192.168.88.0/24 and with the default gateway address 192.168.88.1:

Docker network create -d l2bridge –subnet=192.168.88.0/24 --gateway=192.168.88.1
L2BridgeNet

Linux containers on Windows

If you configure Docker to run in Experimental mode, you can run Linux containers on a Windows Server computer that supports the Hyper-V Isolation mode concurrently with containers based on Windows Server images.

To configure Docker to run in the Experimental mode, edit the daemon.json in the c:programdatadockerconfig folder, and add this line:

{
    "experimental":true
}

You’ll then need to run the following command from an elevated command prompt to set the appropriate environment variable:

[Environment]::SetEnvironmentVariable("LCOW_SUPPORTED", "1", "Machine")

You’ll also need to go to the following GitHub repository at https://github.com/linuxkit/lcow/releases and download the files named initrd.img and kernel and place them in the C:Program FilesLinux Containers folder, as shown in Figure 10-20.

This screenshot shows the files required for Linux Containers on Windows.

Figure 10-20 Files required for Linux Containers on Windows

Once you’ve performed these steps, restart the Docker service by running this command:

Restart-service *docker*

Once you’ve taken these steps, you’ll be able to execute the following command to pull and run a Linux image, such as busybox, as shown in Figure 10-21.

docker run --platform linux busybox uname -a
This screenshot shows the output of a Linux containers running on Windows Server.

Figure 10-21 A Linux container running on Windows Server

You only need to use the --platform option the first time you run a container that needs to be retrieved from a repository.

Container orchestration

Container Orchestration allows you to perform the following tasks with containers:

  • Scheduling. Allows container instances to be started on specific container hosts that participate in the orchestration based on the container host load.

  • Affinity. Allows you to ensure that container instances that need to be near each other are kept in proximity. Can also be configured using anti-affinity to ensure that container instances that need to be highly available are kept on separate container hosts.

  • Health monitoring. Determines which containers may have become unresponsive and replaces them with functional container instances.

  • Failover. Tracks the container hosts. If a container host fails, the container instances that were running on that host are started on another host.

  • Scaling. Allows new instances of containers to be started or stopped to meet the demand on the application. As load increases, the orchestrator starts containers. As load decreases, the orchestrator stops containers.

  • Networking. Creates a special overlay network that allows containers to communicate when hosted on separate container hosts.

  • Service discovery. Allows containers to track other containers as those containers are shifted between container hosts and as they change IP addresses.

  • Application upgrades. Orchestration can ensure that containers are upgraded in such a way that application down time is minimized. Orchestration can also ensure that rollback occurs in the event that an upgrade causes problems.

Docker on Windows Server supports two forms of orchestration: Kubernetes and Docker Swarm.

Kubernetes

A Windows Server container host can participate in a Linux-based Kubernetes orchestration cluster. This allows Windows Server–based container images to take advantage of Kubernetes orchestration. In Windows Server 2019, a Kubernetes cluster must be managed by a Linux server, and you cannot deploy a Windows Server–only Kubernetes cluster. Both Linux worker container hosts and Windows Server container hosts can participate in the same Kubernetes cluster.

Docker Swarm

Docker Swarm mode provides container orchestration. This includes native clustering of container hosts and scheduling of container workloads. You can configure a collection of container hosts to form a swarm cluster. To do this, you need to configure the Docker Engine on the container hosts to run together in Swarm mode.

Swarms include two types of container hosts:

  • Manager nodes. Swarms are initialized from Manager nodes. All Docker commands for the control and management of the swarm must be run from a Manager node. A swarm must have at least one Manager node, but it’s possible for a swarm to have multiple Manager nodes. Manager nodes ensure that the state of the swarm matches the intended state. They keep track of services running on the swarm.

  • Worker nodes. Manager nodes assign Worker nodes tasks that the Worker nodes execute. Worker nodes use a join token, which are generated during swarm initialization to join a swarm.

Swarm mode has the following requirements:

  • Docker Engine v1.13.0 or later

  • TCP port 2377 for cluster management communication open on each node

  • TCP and UDP port 7946 for intra-node communication

  • TCP and UDP port 4789 for overlay network traffic

Creating swarm clusters

Run the following command on the container host that will function as a Manager node and specify the IP address of the container host:

Docker swarm init --advertise-addr <container_host_ip> --listen-addr
<container_host_ip>:2377

The container host will now function as the first Manager node in a new Docker swarm. Running the Docker swarm init command will also generate a join token that you will use to add other nodes to the swarm. You can retrieve the Worker node join token at any point in the future from the Manager node by running the following command:

Docker swarm join-token worker -q

Joining additional Manager nodes requires the Manager node join token. You can retrieve the Manager node join token at any point by running the following command on the Manager node.

Docker swarm join-token manager -q

You can add container hosts to the swarm as Worker nodes by running the following command:

Docker swarm join --token <worker-join-token> <manager_container_host_ip>

You can add container hosts as additional Manager nodes to the swarm by running the following command:

Docker swarm join --token <manager-join-token> <manager_container_host_ip>

You can view which nodes are members of a swarm by running the command:

Docker node ls
Creating overlay networks

Overlay mode allows container endpoints to be connected across multiple container hosts. In a multi-node environment, VXLAN (Virtual Extensible LAN) encapsulation occurs in VFP (Virtual Filtering Platform) forwarding extensions included in the Hyper-V virtual switch. Inter-host communications directly reference IP endpoints. In single-node environments, intra-host communication occurs through a bridged connection on the Hyper-V virtual switch.

You can create an overlay network by running the following command from a Manager node, where 10.0.10.0/24 defines the overlay network address space:

Docker network create --driver=overlay --subnet=10.0.10.0/24 <OverlayNetworkName>
Deploying and scaling swarm services

A swarm service consists of a specific container image that you want to run in multiple instances across nodes in the swarm cluster. Docker Swarm allows you to scale the service as required. For example, if you had a container image that allowed you to deploy a front-end web server for a multi-tier application, you can deploy that container image as a swarm service. As requirements dictate, you can increase the number of container instances by scaling the swarm service. Traffic can be automatically load balanced across the swarm service using DNS Round-Robin. This is substantially simpler than starting new container instances across separate container hosts and manually configuring load balancing to take account of the new container instances.

To create a swarm service, you use the Docker service create command to specify the service name, network name, and container image name, and to set the Endpoint mode to DNS Round-Robin. For example, to create a service named SWARMFRONT using the WEBFRONTEND container image and the OverNet overlay network, issue this command:

Docker service create –name=SWARMFRONT --endpoint-mode=dnsrr --network=OverNet
WEBFRONTEND

Once the service is created, you can scale it using the Docker service scale command and specifying the number of container instances. For example, to scale the SWARMFRONT service to 10 instances, run this command:

Docker service scale SWARMFRONT=10

You can have more than one service present on a Docker Swarm. You can view which services are present by running the following command on a Manager node:

Docker service ls

You can view which container instances make up a service, including which swarm nodes individual containers are running on, by running the following command:

Docker service ps <servicename>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.144.248