Module 3: Create and run a Docker application
Static site
Firstly, we will start step by step to deploy one static web site with nginx.
$ mkdir simple-site
$ cat > simple-site/index.html <<'EOF'
<html>
<head>
<title>Docker workshop</title>
</head>
<body>
<h1>Hello Docker workshop - my static site.</h1>
</body>
EOF
Next step, we download nginX image and run container directly by docker run
, the --rm
flag automatically removes the container when it exits.
$ sudo docker run --name static-site -v /home/workshop/simple-site:/usr/share/nginx/html:ro --rm nginx
The -v
flag is used to mount volume from host to container. Awesome, our website is up and running, but how can we see it?
$ sudo docker exec -it static-site bash
....
$ curl http://localhost
Currently, Docker is not exposing any port to host. We re-run docker run
with -p
to publish port.
$ sudo docker run --name static-site -v /home/workshop/simple-site:/usr/share/nginx/html:ro -p 32769:80 -d nginx
In the above command, -p
flag is used to publish port from container to host, syntax [host port]
:[container port]
In the browser http://workshop-vm-[x].eastasia.cloudapp.azure.com:32769/
Our first image
It is time to build and own Docker images. In this section, we will create one Docker image for Contact service, based on .Net Core 3.0 previce 8
. Besides, it also guides you how to deploy Postgres by container and connect them together.
Fristly, please clone the repository locally.
$ git clone https://github.com/tungphuong/crm.git
$ cd crm/
Dockerfile
In "Contact" service directory has a Dockerfile. It starts by FROM
keyword
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview8-bionic AS builder
Configuring the working directory in container
WORKDIR /src
The next steps is to write commands of:
- Coping file, folder installing the dependencies...
COPY ["src/BuildingBlocks/CRM.Shared/*.csproj", "src/BuildingBlocks/CRM.Shared/"]
COPY ["src/BuildingBlocks/CRM.Migration/*.csproj", "src/BuildingBlocks/CRM.Migration/"]
...
- Restoring packages
RUN dotnet restore src/Contact/CRM.Contact.Api/ /property:Configuration=Release ${feed} -nowarn:msb3202,nu1503
- Building project
RUN dotnet publish src/Contact/CRM.Contact.Api/ -c Release -o /app --no-restore
The next thing is to set environment variables
ENV ASPNETCORE_URLS http://*:80
ENV ASPNETCORE_ENVIRONMENT docker
Last one is to specify the port number and the command for running the service
EXPOSE 80
ENTRYPOINT [ "dotnet", "CRM.Contact.Api.dll"]
Our Dockerfile is ready and looks like
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview8-bionic AS builder
ARG feed='--source "https://api.nuget.org/v3/index.json"'
WORKDIR /src
COPY ["src/BuildingBlocks/CRM.Shared/*.csproj", "src/BuildingBlocks/CRM.Shared/"]
COPY ["src/BuildingBlocks/CRM.Migration/*.csproj", "src/BuildingBlocks/CRM.Migration/"]
COPY ["src/Contact/CRM.Contact.Contract/*.csproj", "src/Contact/CRM.Contact.Contract/"]
COPY ["src/Contact/CRM.Contact.Api/*.csproj", "src/Contact/CRM.Contact.Api/"]
RUN dotnet restore src/Contact/CRM.Contact.Api/ /property:Configuration=Release ${feed} -nowarn:msb3202,nu1503
RUN dotnet restore src/BuildingBlocks/CRM.Migration/ /property:Configuration=Release ${feed} -nowarn:msb3202,nu1503
COPY ["src/BuildingBlocks/CRM.Shared/.", "src/BuildingBlocks/CRM.Shared/"]
COPY ["src/BuildingBlocks/CRM.Migration/.", "src/BuildingBlocks/CRM.Migration/"]
COPY ["src/Contact/CRM.Contact.Contract/.", "src/Contact/CRM.Contact.Contract/"]
COPY ["src/Contact/CRM.Contact.Api/.", "src/Contact/CRM.Contact.Api/"]
RUN dotnet publish src/Contact/CRM.Contact.Api/ -c Release -o /app --no-restore
FROM builder AS migration
WORKDIR /src/src/BuildingBlocks/CRM.Migration/
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0.0-preview8-bionic
WORKDIR /app
ENV ASPNETCORE_URLS http://*:80
ENV ASPNETCORE_ENVIRONMENT docker
COPY --from=builder /app .
EXPOSE 80
ENTRYPOINT [ "dotnet", "CRM.Contact.Api.dll"]
Build image from Dockerfile
$ sudo docker build -t crmnow/contact-api -f src/Contact/CRM.Contact.Api/Dockerfile .
Sending build context to Docker daemon 2.223MB
Step 1/23 : FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview8-bionic AS builder
---> 152368392bc4
Step 2/23 : ARG feed='--source "https://api.nuget.org/v3/index.json"'
---> Using cache
---> 0751506e9318
Step 3/23 : WORKDIR /src
---> Using cache
---> 9414cf4a0d7f
Step 4/23 : COPY ["src/BuildingBlocks/CRM.Shared/*.csproj", "src/BuildingBlocks/CRM.Shared/"]
---> e8c842891507
Step 5/23 : COPY ["src/BuildingBlocks/CRM.Migration/*.csproj", "src/BuildingBlocks/CRM.Migration/"]
---> abf5ef0a4fc6
Step 6/23 : COPY ["src/Contact/CRM.Contact.Contract/*.csproj", "src/Contact/CRM.Contact.Contract/"]
---> 2266cf6ea797
Step 7/23 : COPY ["src/Contact/CRM.Contact.Api/*.csproj", "src/Contact/CRM.Contact.Api/"]
---> 17077cbc16de
Step 8/23 : RUN dotnet restore src/Contact/CRM.Contact.Api/ /property:Configuration=Release ${feed} -nowarn:msb3202,nu1503
---> Running in 9c30eb05086a
....
Step 23/23 : ENTRYPOINT [ "dotnet", "CRM.Contact.Api.dll"]
---> Running in e0b1f832d22d
Removing intermediate container e0b1f832d22d
---> 1ae9e139107b
Successfully built 1ae9e139107b
Successfully tagged crmnow/contact-api:latest
Create "Contact" container from the above image.
$ sudo docker run -p 5200:80 crmnow/contact-api:latest
[08:49:01 INF {"SourceContext": "Microsoft.Hosting.Lifetime", "Environment": "docker", "ApplicationName": "Contact-Service"}] Now listening on: http://[::]:80
[08:49:01 INF {"SourceContext": "Microsoft.Hosting.Lifetime", "Environment": "docker", "ApplicationName": "Contact-Service"}] Application started. Press Ctrl+C to shut down.
[08:49:01 INF {"SourceContext": "Microsoft.Hosting.Lifetime", "Environment": "docker", "ApplicationName": "Contact-Service"}] Hosting environment: docker
[08:49:01 INF {"SourceContext": "Microsoft.Hosting.Lifetime", "Environment": "docker", "ApplicationName": "Contact-Service"}] Content root path: /app
In the browser http://workshop-vm-[x].eastasia.cloudapp.azure.com:5200/swagger/index.html
Congratulations! You have successfully created your first docker image.
Docker push
The first thing that we need to do defore we deploy our app to Azure or any cloud is to publish docker image on a registry. There are many Docker registry such as Docker Hub, ACR,... For now, let's assume that you had one contrainer registry on ACR. To publish, follow below steps
docker login [your ACR].azurecr.io
Username:
Password:
WARNING! Your password will be stored unencrypted in /home/workshop/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
Tag the image
docker tag crmnow/contact-api acrworkshophub.azurecr.io/crmnow/contact-api:v1
Push it
docker push acrworkshophub.azurecr.io/crmnow/contact-api:v1
Logout
docker logout acrworkshophub.azurecr.io