How to Run a Dotnet 8 CLI App in a Docker Container
Date: 2024-08-14 | create | tech | dotnet | docker | containers |
I recently shared a dotnet CLI script that calls Open AI's GPT-4o API using F#. I ran that script (and most of my dotnet apps) in a Docker container so here I'll share how I used Docker to build and run my dotnet CLI app.
Dotnet CLI Script
The example CLI script is simple. I used the dotnet CLI to create a base CLI app for F# then added in my extra logic on top of that.
You could certainly just run the script directly with dotnet run
but I prefer containers to create deterministic dev environments. This makes Infrastructure-as-Code (IaC) possible and I find it makes it easier to run and share my code across people / environments - useful for sharing examples and also deploying to various cloud environments.
Learn more: Create a new F# project from the command line
Containerizing Dotnet 8 CLI Scripts
In this example I'm containerizing an F# script targeting Dotnet 8. This will also work for C# you just need to change the Docker file to look for a .csproj
instead of a .fsproj
.
To containerize our Dotnet 8 app we need to create a Dockerfile
with two steps - A Build Step and a Run Step.
Build Step:
- Create an environment with the dotnet 8 SDK - here we use the official Microsoft dotnet/sdk image
- Copy our
.fsproj
and restore dependencies - We do this in a separate step from publish so that dependencies are cached between builds since this is expensive and changes infrequently - Copy source code and publish app
Run Step:
- Create a new environment with
dotnet/runtime
image - We use a new layer so that the build can be cached between runs and because we can use a smaller image which is nice for data transfers (runtimes are usually much smaller than SDKs) - Copy in our published app from the Build Step
- Run the app (here mine is called
2024-07_ai-cli-example
)
Want the full project files so you can run this example yourself? HAMINIONs members get full access to example project source code so you can quickly clone and run each example. See: Example Dockerfile in live project.
Dockerfile
# **Build Project**
# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
EXPOSE 80
WORKDIR /source
# Copy fsproj and restore all dependencies
COPY ./*.fsproj ./
RUN dotnet restore
# Copy source code and build / publish app and libraries
COPY . .
RUN dotnet publish -c release -o /app
# **Run project**
# Create new layer with runtime, copy app / libraries, then run dotnet
FROM mcr.microsoft.com/dotnet/runtime:8.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "2024-07_ai-cli-example.dll"]
Running dotnet 8 CLI app Docker Container
To run the CLI script in my docker container, I use: docker run --rm -it $(docker build -q .)
This looks a bit cryptic but basically it:
- Builds the docker container in the current directory
- Runs the container in interactive mode - useful for apps that want CLI input
- Removes the container after usage - helpful to prevent naming collisions / zombie containers later
Next
I'm a big fan of containers. They're the simplest scalable system I've found for declaring Infrastructure-as-Code for projects large and small. I find this removes a lot of the pain of sharing project code - to other people, deploying to various clouds, running on different computers / OSes, etc.
If you're interested in seeing what a production web app looks like that uses containers to setup dev and prod deterministic builds, you might be interested in CloudSeed. This is my F# project boilerplate I use to start all my webapps and it uses Docker containers to spin up local dev environments (including a full local database) and publishes its web app as a container for easy deploy to any cloud serverless container offering.
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.