This demo will take you through a process of building and testing a web application locally. We will be using Docker Desktop Enterprise (DDE) to scaffold an application, we'll then push the docker image up to a private image registry (signing the image using Docker Content Trust (DCT)), and automatically scan and promote the repository using Docker Trusted Registry (DTR). Once we have completed this phase of the development process we will run the web application Docker Universal Control Plane (UCP) on a Kubernetes cluster.
(NB we can also use Docker Swarm as the orchestration engine (works great for Windows workloads as well as Linux based workloads).
Ensure Docker Desktop Enterprise is installed on your machine. If you are using Docker for Windows or Docker for Mac, you're good to go. If not, you can download DDE from https://hub.docker.com/editions/community/docker-desktop-ent
Ensure that you have login credentials for Docker Enterprise Platform 3.0 hosted at https://ucp.west.us.se.dckr.org/
Create a respository named catweb within DTR (https://dtr.west.us.se.dckr.org/) and set-up mirroring to DockerHub, a promotion to a production namespace, and optionally a webhook to Slack.
Within a terminal set your env variable for DTR and login to DTR
$ export DTR=dtr.west.us.se.dckr.org
$ echo $DTR
$ docker login $DTR -u <uname> -p <password>
In a shell, you can enable content trust by setting the DOCKER_CONTENT_TRUST environment variable. Enabling per-shell is useful because you can have one shell configured for trusted operations and another terminal shell for untrusted operations. You can also add this declaration to your shell profile to have it turned on always by default.
To enable docker content trust in a bash shell enter the following commands to set the env var and view it
$ export DOCKER_CONTENT_TRUST=1
$ echo $DOCKER_CONTENT_TRUST
1
Visual Studio Code from https://code.visualstudio.com/downloadThere are two parts to the demo. The first part will take you through the process of quickly creating a net new cloud native application in a matter of seconds. The process takes you through scaffolding an application based on the Cloud Native Application Bundle (CNAB) specification using Docker Application Designer within Docker Desktop Enterprise. The second part will go through the process of using GitHub, DDE, DTR, and UCP.
This demo is designed to show a build, share, run Docker workflow using a simple Flask-based web app, catweb.
The basic flow is to initially build and run the app locally using Docker Desktop Enterprise, modify the web template to show how hot mounting a volume works, pushing the image to Docker Trusted Registry optionally signing the image with Docker Trusted Registry, then deploying onto AWS using Docker Universal Control Plane.
Moby icon in your system tray and navigate around the interesting options, explaining each one in turn.Design new application..., Custom application and explain the different available services and associated ports etc.< and then select Choose a templateFlask / NGINX / MySQL application, leave the ports as default and click ContinuedemoApp and select ScaffoldShow logs and describe the process that DDE is going throughHide logs (optional), Run application, view the application by opening a web browser and entering http://localhostOpen in Visual Studio Code and describe the folder and file structure, and the docker files that were generateddocker ps in a terminal to view the running containerWe have not had to learn how to create our Dockerfile(s), docker-compose.yaml, or create the folder and file structure, a bonus being that we have a skeleton application which is up and running in less than a minute.
Now that we have our scaffolded (skeleton) Flash / NGINX / MySQL Server application, we can build upon this and create our net new cloud native application for our project
Stop to stop the application, then click the back < chevrondelete icon, confirm and remove application, and exit x the Application Designer UIcatweb sample GitHub repo too.$ cd ~/Documents/Docker/Demonstrations
$ git clone https://github.com/jas-atwal/catweb.git
Cloning into 'catweb'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 291 (delta 2), reused 0 (delta 0), pack-reused 285
Receiving objects: 100% (291/291), 59.90 KiB | 285.00 KiB/s, done.
Resolving deltas: 100% (161/161), done.
List the files within the directory
$ cd catweb
$ ls
COMMANDS.md README.md catweb-deployment.yaml expose-service.yaml src
Dockerfile app.py docker-compose.yml requirements.txt templates
Notice that we have a
Dockerfileand adocker-compose.yamlfile
Within VS Code open the catweb folder, then open the Dockerfile and explain the how the app is built. You can also show the source code if you wish
Build the app (explain that Docker is going through each step within the Dockerfile in the specified order), and use the docker image command to view the details of the built image
$ docker build --no-cache -t catweb .
Successfully built fd80b366dad9
Successfully tagged catweb:latest
Tagging alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb as alpine:latest
Let's view the generated image
$ docker image ls | grep catweb
catweb latest fd80b366dad9 2 minutes ago 74.1MB
docker-compose. Open the docker-compose.yaml file within VS Code and describe the contents. Now let's run the app on Docker Swarm as the orchestration engine using the commands contained within the docker-compose file.$ docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.
Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.
To deploy your application across the swarm, use `docker stack deploy`.
Creating catweb_web_1 ... done
Attaching to catweb_web_1
web_1 | * Serving Flask app "app" (lazy loading)
web_1 | * Environment: development
web_1 | * Debug mode: on
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 316-525-960
Open a second terminal and view the running container using
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7c9ba2ff21b2 catweb_web "python3 /usr/src/ap…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp catweb_web_1
Open a web browser and show the app running at http://localhost:5000
Open the templates/index.html file within VS Code and update the html tag <h4>Catweb - Curated Cat Gifs!</h4> by adding your name
<h4>Catweb - Jas' Curated Cat Gifs!</h4>
Refresh the web page at http://localhost:5000 and notice the change.
Stop the container using CTRL+C
^CGracefully stopping... (press Ctrl+C again to force)
Stopping catweb_web_1 ... done
docker stack deploy, and docker swarm for orchestration. We can check the running containers using docker ps or docker container lsNote We can also run the containers locally using Kubernetes as the orchestrator
$ docker stack deploy -c docker-compose-prod.yml catweb
Creating network catweb_default
Creating service catweb_web
Let's view the app at http://localhost:5000. Refresh the browser and notice the Container ID changes occasionally. This is because we are running three instances of the application in three separate networked containers and the traffic is being load balanced between them.
View the three running containers
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
438d7ec74910 catweb:latest "python3 /usr/src/ap…" 4 minutes ago Up 4 minutes 5000/tcp catweb_web.1.5bqnigtauc6ewd1jrts10lm7v
a6d46717c3e1 catweb:latest "python3 /usr/src/ap…" 4 minutes ago Up 4 minutes 5000/tcp catweb_web.2.uvcfnuaxsyg0wffosupokrt5q
17665d8af3c3 catweb:latest "python3 /usr/src/ap…" 4 minutes ago Up 4 minutes 5000/tcp catweb_web.3.azc8ed275lfeyzwfd1xap38rd
STATUS$ docker container kill 438d7ec74910
438d7ec74910
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8610e3297c89 catweb:latest "python3 /usr/src/ap…" 8 seconds ago Up 4 seconds 5000/tcp catweb_web.1.p9o12hs072rbzfy27cjm10ocr
a6d46717c3e1 catweb:latest "python3 /usr/src/ap…" 5 minutes ago Up 5 minutes 5000/tcp catweb_web.2.uvcfnuaxsyg0wffosupokrt5q
17665d8af3c3 catweb:latest "python3 /usr/src/ap…" 5 minutes ago Up 5 minutes 5000/tcp catweb_web.3.azc8ed275lfeyzwfd1xap38rd
Notice how a new container has been stood up in place of the container that we killed and has only been up a few seconds
We are now ready to share the image using Docker Trusted Registry , during which we will also sign and scan the image for vulnerabilities.
Now that the docker image has been built and we have successfully tested the running of the catweb application locally, we can push the image up to Docker Trusted Registry so that we can sign, scan, and promote the image from dev through to production for final deployment.
tag the image and then push this tagged image to our private registry (DTR) ensuring that you use your own namespace (replace se-jasatwal with your namespace)$ docker tag catweb:latest $DTR/se-jasatwal/catweb:latest
$ docker image ls | grep catweb
catweb_web latest cc5142167446 51 minutes ago 74.1MB
catweb latest ebbdcec5a92d About an hour ago 74.1MB
dtr.west.us.se.dckr.org/se-jasatwal/catweb latest ebbdcec5a92d About an hour ago 74.1MB
$ docker push $DTR/se-jasatwal/catweb:latest
The push refers to repository [dtr.west.us.se.dckr.org/se-jasatwal/catweb]
aa9ff091b287: Pushed
164e79b62389: Pushed
2f6e52a272df: Pushed
8d4536d51aeb: Pushed
13806d62f1e3: Pushed
226cecc8e243: Pushed
03901b4a2ea8: Layer already exists
latest: digest: sha256:2d9db17f7849327fe7c53e5e90e3b9c7398820acd189bc24a97536f59742f3c3 size: 1783
Signing and pushing trust metadata
Enter passphrase for repository key with ID 7d9b31d:
Successfully signed dtr.west.us.se.dckr.org/se-jasatwal/catweb:latest
The
DTRwhich we are using for this demo isdtr.west.us.se.dckr.org
If you have enabled
DOCKER_CONTENT_TRUST=1as anenvironment variablethen the first time youpushan image usingcontent truston your system, the session looks like this:
Signing and pushing trust metadata
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
Enter passphrase for new root key with ID fa0e171:
Enter a passphrase when prompted.
Make note of this
passphraseas it is not retrievable if forgotten.
Once complete you will receive a response similar to that below
Finished initializing "dtr.west.us.se.dckr.org/se-jasatwal/catweb"
Successfully signed dtr.west.us.se.dckr.org/se-jasatwal/catweb:latest
Click on Repositories and within the Filter by: All Namespaces enter your namespace name, select the catweb repositories and select the tag first to show the image that you just uploaded. Then discuss the automation of:
image signing
image scanning,
image mirroring
image promotions and
webhooks

Now that the image has been pushed to our private registry, has been signed, scanned, and promoted through to our production namespace, let's run the web application within a container on Kubernetes via Docker Universal Control Plane UCP.
We can run the container using a
Kubernetes yamlfile or alternatively via thecommand line. We will use the latter!
Kubernetes deployment using the image that you pushed up to DTR and check it exists$ kubectl create deployment catweb --image=$DTR/se-jasatwal/catweb
deployment.apps/catweb created
$ kubectl get deploy | grep catweb
catweb 1/1 1 1 30s
Where
se-jasatwalis your namespace inDTR. If you have not set theDTR environment variableplease substitute$DTRwithdtr.west.us.se.dckr.org
Kubernetes service exposing port 5000 and using type LoadBalancer$ kubectl expose deployment catweb --port=5000 --type=LoadBalancer
service/catweb exposed
$ kubectl get pod | grep catweb
catweb-5c6d4b9c95-z8f4f 1/1 Running 0 5m49s
EXTERNAL IP address which you will need in the next step$ kubectl get svc
$ kubectl get svc | grep catweb
catweb LoadBalancer 10.96.33.124 a3c5da531eb2111e9a6fb0242ac11000-757615726.us-west-2.elb.amazonaws.com 5000:35435/TCP 3h27m
If the EXTERNAL_IP is showing as pending, please wait a few seconds and run the
kubectl get svc | grep catwebcommand again until it returns a string as above.
Kubernetes cluster on AWS via the Docker Enterprise Platform.NOTE: the external_ip address in the example above is a3c5da531eb2111e9a6fb0242ac11000-757615726.us-west-2.elb.amazonaws.com
UCP Dashboard and navigate around the aspects such as Access Control, Kubernetes Services and Pods etc.
$ kubectl scale --replicas=5 deployment/catweb
deployment.extensions/catweb scaled
(5/5 replicas created)$ kubectl describe deployment catweb
Name: catweb
Namespace: se-jasatwal
CreationTimestamp: Mon, 14 Oct 2019 12:50:41 +0100
Labels: app=catweb
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=catweb
Replicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=catweb
Containers:
catweb:
Image: dtr.west.us.se.dckr.org/se-jasatwal/catweb
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Progressing True NewReplicaSetAvailable
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: catweb-5c6d4b9c95 (5/5 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m25s deployment-controller Scaled up replica set catweb-5c6d4b9c95 to 5
Review the
Eventssection towards the bottom of the output. We have successfully scaled out to five ReplicaSets.
You have successfully containerised an application, tested it locally, pushed it up to a private registry, signed, scanned, and promoted the image, then deployed the application to Kubernetes. All using the Docker Enterprise Platform - the only end-to-end secure software supply chain from DEV to PROD! :grin:
Note: Do this after EACH demo
$ docker image ls | grep catweb
$ docker image rm dtr.west.us.se.dckr.org/se-jasatwal/catweb
$ docker image rm catweb
$ docker ps -a
7c9ba2ff21b2
$ docker container rm 7c9ba2ff21b2
$ kubectl delete deploy catweb
$ kubectl delete svc catweb
$ kubectl get pods
catweb-5c6d4b9c95-z8f4f
$ kubectl delete pod catweb-5c6d4b9c95-z8f4f
$ docker image prune -a
$ cd ..
$ rm -R ~$PWD/catweb/
demoApp application$ rm -R ~/Documents/Docker/Demonstrations/app-designer/demoApp
Note: The location of your Application Designer application files will differ from that above
In a web browser navigate to https://ucp.west.us.se.dckr.org/. If prompted to log in, please do so
From the left menu, click Swarm, then Services
Click the Create button and fill in the following values replacing se-jasatwal with your namespace
dtr.west.us.se.dckr.org/se-jasatwal/catweb:latestNetwork select Add Port+5000, and 5000 in the source and target fields respectivelyLabels add two lables:
interlock.hostname and wwwinterlock.domain and catweb.demoNote: Make sure to click the plus after each one
Click Create
After the container is successfully deployed, navigate in the web browser to http://www.catweb.demo. This will navigate to your newly deployed container running on AWS via Docker Enterprise Platform.
Congratulations!! :tada:
Content type
Image
Digest
Size
21.1 MB
Last updated
over 5 years ago
docker pull jasatwal/catweb