Overview

There are times when you are writing projects but require dependent services but you’re not building microservices etc. These might be services which are “just there” in your production environment but need a bit more thought when running locally. One such service might be Redis. Setting up your application to use an in memory distributed cache might be ok but sometimes you need to dev/test against an actual service.

So how do we get Redis running locally on a Windows developer machine with minimal fuss?

Running Redis Options

There are a couple of options to get Redis running locally on a Windows machine:

  1. Memurai - which is a Redis compatible cache and data store - https://www.memurai.com/
  2. Redis on Docker - running a docker container manually

I’m sure there are other options but I’ve not come across them or needed to up until this point. Now there is a new option; running it with Project Tye.

This is the setup we are going to explorer.

Running Redis locally with Project Tye

Project Tye still requires Docker for Windows to be running in the background but then handles the rest for you. Once you have installed Docker for Windows it just runs in the system tray and you dont notice it is there. It needs to be running in Linux container mode.

Note: This post assumes Docker for Windows set for Linux containers running on a Virtual Machine. I have not been able to test this using WSL2 but I would imagine it will work.

To get it working there is no previous work required. No need to know about Docker other than to install Docker for Windows and make sure it is running.

Project Tye has the ability to build and run local projects but also it can start up a container based on the tye config. No need to start a docker container instance yourself from the command line. Once the configuration file is defined it’s really easy to start.

Creating the Configuration File

We start off by creating the project tye configuration file.

To use tye we first have to install it if not already installed. This is a global tool which is installed on the command line.

dotnet tool install -g Microsoft.Tye --version "0.4.0-alpha.20371.1"

Once the tool is installed we can now use it.

At this point you need to start up a powershell prompt, navigate to your required folder location and execute the following command.

tye init

This will create an empty tye configuration file similar to the below.

# tye application configuration file
# read all about it at https://github.com/dotnet/tye
#
# when you've given us a try, we'd love to know what you think:
#    https://aka.ms/AA7q20u
#
# define global settings here
# name: exampleapp # application name
# registry: exampleuser # dockerhub username or container registry hostname

# define multiple services here
services:
- name: myservice
  # project: app.csproj # msbuild project path (relative to this file)
  # executable: app.exe # path to an executable (relative to this file)
  # args: --arg1=3 # arguments to pass to the process
  # replicas: 5 # number of times to launch the application
  # env: # array of environment variables
  #  - name: key
  #    value: value
  # bindings: # optional array of bindings (ports, connection strings)
    # - port: 8080 # number port of the binding

We can then start to configure the redis “services”. This configuration is based on the tye example on the microsoft blog - https://devblogs.microsoft.com/aspnet/introducing-project-tye/ - to configure both the redis instance and the redis cli to monitor the service.

name: your-application
services:
- name: redis
  image: redis
  bindings:
  - port: 6379
    connectionString: "${host}:${port}"
  tags:
    - redis

- name: redis-cli
  image: redis
  args: "redis-cli -h redis MONITOR"
  tags:
    - redis

As you can see in the above we are defining a redis service and specifying the image name. This is the name of the docker image which can be found on Docker Hub. If your local container image cache does not have this image Tye will download the images, through Docker, as required.

What are tags?

Tags are a system to allow for grouping multple services together. In doing this you can start up all the services or a subset of the services when you execute the tye run command. For example if you are working on a backend api service and need a database you could add a “backend” tag to the webapi and the database service. Extending the above you could run a “frontend” tag which runs the a web application but you may want redis to do the caching so you would add the same tag to the redis services above.

Running the Dependencies

Now we have a configuration file setup we can run our redis services. In this example we are running it will explicit tags value specified. This is not requires in this scenario as we want all the services which are defined to run but shows how different configurations could be executed.

tye run --tags=redis

On executing the above command for the first time you will now see something like the below.

[16:33:17 INF] Executing application from C:\Temp\src\playgound\tye.yaml
[16:33:17 INF] Dashboard running on http://127.0.0.1:8000
[16:33:23 INF] Running docker command pull redis
[16:33:25 INF] redis: Using default tag: latest
[16:33:27 INF] redis: latest: Pulling from library/redis
[16:33:27 INF] redis: bf5952930446: Pulling fs layer
[16:33:27 INF] redis: 911b8422b695: Pulling fs layer
[16:33:27 INF] redis: 093b947e0ade: Pulling fs layer
[16:33:27 INF] redis: c7616728f575: Pulling fs layer
[16:33:27 INF] redis: 61a55f107028: Pulling fs layer
[16:33:27 INF] redis: 0ee3e0cb4e07: Pulling fs layer
[16:33:27 INF] redis: c7616728f575: Waiting
[16:33:27 INF] redis: 61a55f107028: Waiting
[16:33:27 INF] redis: 0ee3e0cb4e07: Waiting
[16:33:29 INF] redis: 093b947e0ade: Download complete
[16:33:29 INF] redis: 911b8422b695: Verifying Checksum
[16:33:29 INF] redis: 911b8422b695: Download complete
[16:33:30 INF] redis: 61a55f107028: Verifying Checksum
[16:33:30 INF] redis: 61a55f107028: Download complete
[16:33:31 INF] redis: 0ee3e0cb4e07: Verifying Checksum
[16:33:31 INF] redis: 0ee3e0cb4e07: Download complete
[16:33:33 INF] redis: bf5952930446: Verifying Checksum
[16:33:33 INF] redis: bf5952930446: Download complete
[16:33:33 INF] redis: bf5952930446: Pull complete
[16:33:33 INF] redis: 911b8422b695: Pull complete
[16:33:34 INF] redis: 093b947e0ade: Pull complete
[16:33:34 INF] redis: c7616728f575: Verifying Checksum
[16:33:34 INF] redis: c7616728f575: Download complete
[16:33:34 INF] redis: c7616728f575: Pull complete
[16:33:34 INF] redis: 61a55f107028: Pull complete
[16:33:34 INF] redis: 0ee3e0cb4e07: Pull complete
[16:33:34 INF] redis: Digest: sha256:933c6c01829165885ea8468d87f71127b1cb76a711311e6c63708097e92ee3d1
[16:33:34 INF] redis: Status: Downloaded newer image for redis:latest
[16:33:34 INF] redis: docker.io/library/redis:latest
[16:33:34 INF] Creating docker network tye_network_5052ec16-9
[16:33:34 INF] Running docker command network create --driver bridge tye_network_5052ec16-9
[16:33:36 INF] Running image redis for redis_94e31a66-6
[16:33:36 INF] Running image redis for redis-cli_dcb60d4d-9
[16:33:40 INF] Running container redis_94e31a66-6 with ID 288eef9c3f39
[16:33:40 INF] Running container redis-cli_dcb60d4d-9 with ID caca699aaf85
[16:33:40 INF] Running docker command network connect tye_network_5052ec16-9 redis_94e31a66-6 --alias redis
[16:33:40 INF] Running docker command network connect tye_network_5052ec16-9 redis-cli_dcb60d4d-9 --alias redis-cli
[16:33:42 INF] Replica redis-cli_dcb60d4d-9 is moving to a ready state
[16:33:42 INF] Collecting docker logs for redis-cli_dcb60d4d-9.
[16:33:42 INF] Replica redis_94e31a66-6 is moving to a ready state
[16:33:42 INF] Collecting docker logs for redis_94e31a66-6.

Above you can see it executing all the Docker commands to get the required images, pull them down and then use them to create containers for both the redis and redis-cli images.

We now have Redis running locally.

Browsing to the Tye Dashboard on http://127.0.0.1:8000 you will now see 2 services running. The dashboard allows for accessing information about the running instances and access to their logs.

Connecting ASP.NET Core to Redis

Now we have a local Redis instance running all be it in a container we can now access it as if it was running on our local machine directly.

To connect to it one of the options is to add the Microsoft.Extensions.Caching.StackExchangeRedis nuget package to your csproj file through the command line or nuget package manager. The version of the package at time of writing is 3.1.7.

Once installed navigate to the Startup class of your application you set your ConfigureServices method to look similar to the below to add the Redis Client service registrations and configuration into the service collection.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = "localhost:6379";
    });
}

I have hardcoded the connection string in this example to show how simple it is to now access the service. This should come from IConfiguration in production applications. You can now inject a IDistributedCache into your services through dependency injection and start harnessing the power of a distributed caching mechanism backed by Redis.

Conclusion

In this post we have briefly walked through options to running Redis in a local developer environment on Windows. We have looked at how to run Redis in a docker container but have Project Tye deal with the details. We have also given a brief example of how you can now connect your ASP.NET Core application to the running instance.

I hope you have found the above interesting and helpful. Any questions/comments then please contact me on Twitter @WestDiscGolf