Page 12 - MSDN Magazine, June 2019
P. 12

and password. The user id is still in the Dockerfile only because I was focusing on hiding the password and haven’t yet removed it:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base WORKDIR /app
EXPOSE 80
ENV ConnectionStrings:MagsConnectionMssql="Server=[Azure SQL endpoint]; Initial Catalog=DP0419Mags;Persist Security Info=False;
User ID=ENVID;Password=ENVPW;MultipleActiveResultSets=False; Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
ENV DB_UserId="lerman"
FROM microsoft/dotnet:2.2-sdk AS build
This connection string can easily be moved out to docker­ compose.yml and controlled by external means, as well. The API’s Startup Configuration method overwrites the user and password placeholders with the values of provided environment variables, including the password DB_PW that I stored in the.env file whose contents look like this:
DB_PW=eiluj
The .env file and its DB_PW value will be read by docker­compose and passed into the container for the Dockerfile to read and make available to the app. In the end, I’m removing both the connection string and DB_UserId variables from Dockerfile.
But that connection string was for Azure SQL. I now need to change its value to point to the SQL Server container:
ENV ConnectionStrings:MagsConnectionMssql "Server=db;Database=DP0419Mags;User=sa;Password=ENVPW;"
I’m using the same variable name because that’s what Startup.ConfigureServices is expecting. What’s interesting to me is that the container runtime will understand the name of the db service defined in docker­compose as the server name. So, in the connection string, I can specify the server as db. The default user that the mssql/server image uses to set up the server is sa, so I’ve coded that directly into the connection string, which is why I no longer need an ENV variable for the user id. However, I’m still using a placeholder, ENVPW, for the password value.
As with the sample in the previous column, the placeholder will ultimately be replaced by the value of the DB_PW environment variable. Here’s what the code now looks like that reads the connec­
Figure 3 Inspecting the Images
Figure 4 The Running Containers
Figure 5 The Docker Volume Command 8 msdn magazine
tion string and the DB_PW variable, then updates the connection
string before passing it to the SQL Server provider:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); var config = new StringBuilder(
Configuration["ConnectionStrings:MagsConnectionMssql"]); string conn = config.Replace("ENVPW", Configuration["DB_PW"])
.ToString(); services.AddDbContext<MagContext>(options => options.UseSqlServer(conn));
}
Those are all the needed changes! Now let’s debug and see what happens.
Debugging with the Database Container
Be sure that the docker­compose project is the startup project in the solution and that the debug button is set to Docker Compose, then hit F5 to debug the API.
The SQL Server image isn’t small—it’s 1.45GB. So, the first time you pull it, be patient.
If this is the first time you’re running the app this way and you’ve never pulled the mssql/server image, that will be the first thing to happen. The SQL Server image isn’t small—it’s 1.45GB. So, the first time you pull it, be patient. Note that it requires 2GB of RAM, so be sure to assign enough RAM to your Docker engine (in the Docker settings) to run it. Even so, this is still faster than installing SQL Server on your machine, and it only uses resources already assigned to Docker, not additional resources on your host machine. And once the image is there, it’s breezy to spin up lots of instances. Another benefit is that any updates to the base image get pulled as small layers, not the entire thing again. Note that the Microsoft/ dotnet sdk and aspnetcore­runtime images are already on my
system, thanks to the work I did in the previous columns.
If you watch the build output, you’ll see that the app creates the data volume prior to handling the mssql/server container—in my case “handling” means first pulling it from Docker Hub because it’s
new to my system. This order of operations occurs because the server is dependent on the volume, so the volume gets taken care of first. Once that’s done, it starts building up the API’s image if needed and then spins up the containers. The steps are clearly relayed in the build output, thanks to the tooling.
As with the previous versions of this app, the results of the GET method of the Magazines controller are displayed in a browser window.
Data Points


































































































   10   11   12   13   14