Docker For Mac Catalina



-->

In this article, you'll learn how to install .NET on macOS. .NET is made up of the runtime and the SDK. The runtime is used to run a .NET app and may or may not be included with the app. The SDK is used to create .NET apps and libraries. The .NET runtime is always installed with the SDK.

The latest version of .NET is 5.0.

For more information about using.NET Core in a Docker container, see Introduction to.NET and Docker and Samples. How to check if.NET Core is already installed. Working with macOS Catalina notarization. Tutorial: Get started on macOS. Tutorial: Create a new app with Visual Studio Code. Tutorial: Containerize a.NET Core app. Added OS X binary as a directory to solve slow start up time issues caused by macOS Catalina binary scan. Passed the HOME environment variable in container mode when running with script/run/run.sh. Docker Compose now reports images that cannot be pulled, however, are required to be built. 1.25.0 (2019-11-18) New features. Examples from Docker-OSX. In the case example of why these scripts were written is: GENERATEUNIQUE is used as a Docker argument to randomly generate 1 set at runtime, for every new container. GENERATESPECIFIC is used to specify an already known model, serial, board-serial, uuid and MAC address. The registry to push is by default docker.io but can be specified as part of the images’s name name the Docker way. Docker.test.org:5000/data:1.5 will push the image data with tag 1.5 to the registry docker.test.org at port 5000.

Supported releases

The following table is a list of currently supported .NET releases and the versions of macOS they're supported on. These versions remain supported either the version of .NET reaches end-of-support.

Catalina
  • A ✔️ indicates that the version of .NET Core is still supported.
  • A ❌ indicates that the version of .NET Core isn't supported.
Operating System.NET Core 2.1.NET Core 3.1.NET 5.0
macOS 11.0 'Big Sur'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 (Release notes)
macOS 10.15 'Catalina'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 (Release notes)
macOS 10.14 'Mojave'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 (Release notes)
macOS 10.13 'High Sierra'✔️ 2.1 (Release notes)✔️ 3.1 (Release notes)✔️ 5.0 (Release notes)
macOS 10.12 'Sierra'✔️ 2.1 (Release notes)❌ 3.1 (Release notes)❌ 5.0 (Release notes)

Unsupported releases

The following versions of .NET are ❌ no longer supported. The downloads for these still remain published:

  • 3.0 (Release notes)
  • 2.2 (Release notes)
  • 2.0 (Release notes)

Runtime information

The runtime is used to run apps created with .NET. When an app author publishes an app, they can include the runtime with their app. If they don't include the runtime, it's up to the user to install the runtime.

There are two different runtimes you can install on macOS:

  • ASP.NET Core runtime
    Runs ASP.NET Core apps. Includes the .NET runtime.

  • .NET runtime
    This runtime is the simplest runtime and doesn't include any other runtime. It's highly recommended that you install ASP.NET Core runtime for the best compatibility with .NET apps.

SDK information

The SDK is used to build and publish .NET apps and libraries. Installing the SDK includes both runtimes: ASP.NET Core and .NET.

Dependencies

.NET is supported on the following macOS releases:

.NET Core VersionmacOSArchitecturesMore information
5.0High Sierra (10.13+)x64More information
3.1High Sierra (10.13+)x64More information
3.0High Sierra (10.13+)x64More information
2.2Sierra (10.12+)x64More information
2.1Sierra (10.12+)x64More information
Docker for mac catalina dmg

Beginning with macOS Catalina (version 10.15), all software built after June 1, 2019 that is distributed with Developer ID, must be notarized. This requirement applies to the .NET runtime, .NET SDK, and software created with .NET.

The runtime and SDK installers for .NET 5.0 and .NET Core 3.1, 3.0, and 2.1, have been notarized since February 18, 2020. Prior released versions aren't notarized. If you run a non-notarized app, you'll see an error similar to the following image:

For more information about how enforced-notarization affects .NET (and your .NET apps), see Working with macOS Catalina Notarization.

libgdiplus

.NET applications that use the System.Drawing.Common assembly require libgdiplus to be installed.

An easy way to obtain libgdiplus is by using the Homebrew ('brew') package manager for macOS. After installing brew, install libgdiplus by executing the following commands at a Terminal (command) prompt:

Install with an installer

macOS has standalone installers that can be used to install the .NET 5.0 SDK:

Download and manually install

As an alternative to the macOS installers for .NET, you can download and manually install the SDK and runtime. Manual install is usually performed as part of continuous integration testing. For a developer or user, it's generally better to use an installer.

If you install .NET SDK, you don't need to install the corresponding runtime. First, download a binary release for either the SDK or the runtime from one of the following sites:

  • ✔️ .NET 5.0 downloads
  • ✔️ .NET Core 3.1 downloads
  • ✔️ .NET Core 2.1 downloads

Next, extract the downloaded file and use the export command to set variables used by .NET and then ensure .NET is in PATH.

To extract the runtime and make the .NET CLI commands available at the terminal, first download a .NET binary release. Then, open a terminal and run the following commands from the directory where the file was saved. The archive file name may be different depending on what you downloaded.

Use the following commands to extract the runtime or SDK that you downloaded. Remember to change the DOTNET_FILE value to your file name:

Tip

The preceding export commands only make the .NET CLI commands available for the terminal session in which it was run.

You can edit your shell profile to permanently add the commands. There are a number of different shells available for Linux and each has a different profile. For example:

  • Bash Shell: ~/.bash_profile, ~/.bashrc
  • Korn Shell: ~/.kshrc or .profile
  • Z Shell: ~/.zshrc or .zprofile

Edit the appropriate source file for your shell and add :$HOME/dotnet to the end of the existing PATH statement. If no PATH statement is included, add a new line with export PATH=$PATH:$HOME/dotnet.

Also, add export DOTNET_ROOT=$HOME/dotnet to the end of the file.

Docker for mac catalina 10.15

This approach lets you install different versions into separate locations and choose explicitly which one to use by which application.

Install with Visual Studio for Mac

Visual Studio for Mac installs the .NET SDK when the .NET workload is selected. To get started with .NET development on macOS, see Install Visual Studio 2019 for Mac.

Docker For Mac Catalina
.NET SDK versionVisual Studio version
5.0Visual Studio 2019 for Mac version 8.8 or higher.
3.1Visual Studio 2019 for Mac version 8.4 or higher.
2.1Visual Studio 2019 for Mac version 8.0 or higher.

Docker For Mac Catalina Installer

Install alongside Visual Studio Code

Visual Studio Code is a powerful and lightweight source code editor that runs on your desktop. Visual Studio Code is available for Windows, macOS, and Linux.

While Visual Studio Code doesn't come with an automated .NET installer like Visual Studio does, adding .NET support is simple.

  1. Download and install Visual Studio Code.
  2. Download and install the .NET SDK.
  3. Install the C# extension from the Visual Studio Code marketplace.

Install with bash automation

The dotnet-install scripts are used for automation and non-admin installs of the runtime. You can download the script from the dotnet-install script reference page.

The script defaults to installing the latest long term support (LTS) version, which is .NET Core 3.1. You can choose a specific release by specifying the current switch. Include the runtime switch to install a runtime. Otherwise, the script installs the SDK.

Note

The previous command installs the ASP.NET Core runtime for maximum compatability. The ASP.NET Core runtime also includes the standard .NET runtime.

Docker

Containers provide a lightweight way to isolate your application from the rest of the host system. Containers on the same machine share just the kernel and use resources given to your application.

.NET can run in a Docker container. Official .NET Docker images are published to the Microsoft Container Registry (MCR) and are discoverable at the Microsoft .NET Core Docker Hub repository. Each repository contains images for different combinations of the .NET (SDK or Runtime) and OS that you can use.

Microsoft provides images that are tailored for specific scenarios. For example, the ASP.NET Core repository provides images that are built for running ASP.NET Core apps in production.

For more information about using .NET Core in a Docker container, see Introduction to .NET and Docker and Samples.

Next steps

  • How to check if .NET Core is already installed.
  • Working with macOS Catalina notarization.
  • Tutorial: Get started on macOS.
  • Tutorial: Create a new app with Visual Studio Code.
  • Tutorial: Containerize a .NET Core app.

Can’t connect to the server running in your container? Let’s see why, and how to fix it, starting with an example.

If you run a server on your machine listening on 127.0.0.1, the “loopback” or “localhost” address:

You can then load it in your browser at http://127.0.0.1:8000.

But if you kill that and run it in a container:

If you then try to connect with your browser to http://127.0.0.1:8000 you’ll get connection refused or connection reset.

Docker For Mac Catalina Patcher

What’s going on?To understand how to solve this, you need to know a minimal amount about how Docker’s networking works.In particular, this article will cover:

  • Networking namespaces, and how Docker uses them.
  • What docker run -p 5000:5000 does, and why our example above doesn’t work.
  • How to fix your image so the server is accessible.

Networking without Docker

Let’s start with our first scenario: you run a server directly inside your operating system, and then connect to it.I’m going to assume the main OS is Linux, for simplicity of explanation. Docker runs on non-Linux OSes like macOS by running a Linux virtual machine, but the practical consequences are the same.

Your operating system has multiple network “interfaces”.For example, on my computer (with output shortened for clarity):

In this output we see three network interfaces:

  • We’ll ignore docker0 for now.
  • lo is the loopback interface, with IPv4 address 127.0.0.1: it’s your own computer, addressable in-memory without any networking hardware.
  • wlp0s20u8 is my WiFi card, with IPv4 address 192.168.7.202, and when I talk to computers on the Internet the packets are sent via that interface.

Let’s go back to our starting, working example—you run a server listening on 127.0.0.1, and then connect to it.We can visualize it like this:

Network namespaces

You’ll notice the image above talks about a “Default network namespace”.So what’s that?

Docker is a system for running containers: a way to isolate processes from each other.It builds on a number of Linux kernel features, one of which is network namespaces—a way for different processes to have different network devices, IPs, firewall rules, and so on.

By default, each container run by Docker has its own network namespace, with its own IPs:

So this container has two interfaces, eth0 and lo, each with their own IP addresses.But because this is a different network namespace, these are different interfaces than the default namespace we saw above.

To make it clear what this means, let’s run the Flask server inside a Docker container, and then diagram the results:

The resulting network setup looks like this:

Now it’s clear why there’s a connection refused: the server is listening on 127.0.0.1 inside the container’s network namespace.The browser is connecting to 127.0.0.1 in the main, default network namespace.But those are different interfaces, so no connection is made.

How do we connect the two network namespaces? With Docker port-forwarding.

Docker run port-forwarding (is not enough)

If we run docker run with -p 5000:5000, it will forward from all interfaces where the Docker daemon is running (for our purposes, the main network namespace) to the external IP address of the containter.

Docker For Mac Catalina Dmg

To break it down explicitly: -p 5000:5000 means redirecting traffic from port 5000 on all interfaces in the main network namespace to the container’s port 5000 on its external interface.-p 8080:80 would redirect traffic from port 8080 on all interfaces in the main network namespace to port 80 on the container’s external interface. And so on.

(We’re doing port 5000 specifically because that’s where our Docker image is listening, Flask’s default port.)

Docker osx catalina

So let’s run a container, and then look at a diagram to visually see what that means:

And now we see the second problem: the server is listening on 127.0.0.1 inside the container network namespace, but the port forwarding is going to the external IP, 172.17.0.2.

Docker Install Mac Catalina

Thus, a connection reset or refused.

The solution: listen on all interfaces

Port forwarding can only connect to a single destination—but you can change where the server process is listening.You do this by listening on 0.0.0.0, which means “listen on all interfaces”.

For example, you can do:

Docker Osx Catalina

Note:--bind 0.0.0.0 is specifically an option for http.server; it’s not a Docker option.Other servers will have other ways of specifying this.For example, for a Flask application packaged with a Dockerfile, you can do:

Now the network diagram looks like this:

Takeaways

  1. By default, containers run in their own network namespaces, with their own IP addresses.
  2. docker run -p 5000:5000 will forward from all interfaces in the main network namespace (or more accurately, the one where the Docker daemon is running) to the external IP in the container.
  3. You therefore need to listen on the external IP inside the container, and the easiest way to do that is by listening on all interfaces: 0.0.0.0.

Want to quickly get up to speed on Docker packaging? Learn the fundamentals in an afternoon by reading Just Enough DockerPackaging—this article is an excerpt from the book.