Udacity | SUSE: Orchestration - Docker Labs
Tags: 100daysofcode, docker, devjournal, devops
Published: 2021-06-21 16:47:22

> *This is the sixth article in the series,* ***Udacity: SUSE Cloud Native Foundations***. This article will contain the exercises and labs from the previous section about Docker.

---

This section will contain two labs:
- [Lab 1 - Your first containerized Python application](#lab-1-your-first-containerized-app)
- [Lab 2 - Packaging a Go application](#lab-2-packaging-a-go-application)

---

## Lab 1 - Your first containerized app

In this exercise, we'll use the same <code>app.py</code> that we extended and played around in the section [Architecture Considerations - Lab](https://dev.to/eden_jose08/udacity-suse-architecture-considerations-lab-305g).

If you skipped that section, no worries! You can simply clone the repository:

```bash
$ git clone https://github.com/udacity/nd064_course_1.git
```

Go to <code>exercises/python-helloworld</code> folder. Here you should see the <code>app.py</code>

```bash
$ cd nd064_course_1/

$ ls -l
total 25
drwxr-xr-x 1 Eden Jose 197610  0 Jun 18 19:41 exercises/
drwxr-xr-x 1 Eden Jose 197610  0 Jun 18 19:41 project/
-rw-r--r-- 1 Eden Jose 197610 12 Jun 18 19:41 README.md
drwxr-xr-x 1 Eden Jose 197610  0 Jun 18 19:41 solutions/

$ cd exercises/python-helloworld/

$ ls -l
total 6
-rw-r--r-- 1 Eden Jose 197610 167 Jun 18 19:41 app.py
-rw-r--r-- 1 Eden Jose 197610  32 Jun 18 19:41 requirements.txt
```
Please note that in the  [Architecture Considerations - Lab](https://dev.to/eden_jose08/udacity-suse-architecture-considerations-lab-305g), we extended the code, so the code that is in this folder is the original one. You can simply modify it:

```python
from flask import Flask
from flask import json

app = Flask(__name__)

@app.route('/status')
def status():
response = app.response_class(
        response=json.dumps({"result":"OK - healthy"}),
        status=200,
        mimetype='application/json'
)

return response

@app.route('/metrics')
def metrics():
response = app.response_class(
        response=json.dumps({"status":"success","code":0,"data":{"UserCount":140,"UserCountActive":23}}),
        status=200,
        mimetype='application/json'
)

return response

@app.route("/")
def hello():
return "Hello World!"

if __name__ == "__main__":
app.run(host='0.0.0.0')
```

Still in the same folder, you should also see a <code>requirements.tx</code>. This is important because we will specify this as a dependency in the dockerfile.

```bash
$ cat requirements.txt 
Flask==1.1.1
werkzeug==0.16.1
```
Now, we first begin writing our dockerfile with the instructions.
```docker
FROM python:3.9
LABEL maintainer="Eden Jose"

COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt

CMD [ "python", "app.py"]

# Since we're deploying a python application, we'll be using a python base image
# The LABEL is used to add description or metadata
# COPY copies any files in the current folder in the host to the container
# WORKDIR sets the working directory
# RUN runs the install command. Installs all specified in requirements.txt
# CMD allows specifying a command.
# Command specified is to run the python application
```
Make sure docker is installed in your machine. You can follow this link to [install docker](https://docs.docker.com/engine/install/).
Next step is to build the image. Building the image will take time since it has to install the python.
```bash
# -t tags the image with the name specified.
docker build -t udacity-python-helloworld .
```
Once done, run this command to check if your image has been created.
```bash
docker images

REPOSITORY                       TAG          IMAGE ID       CREATED              SIZE
udacity-suse-python-helloworld   latest       8ac51fb8decf   About a minute ago   894MB
```

To test locally, we can run the container based on the image
```bash
docker run -d -p 5000:5000 udacity-suse-python-helloworld

# -d means container will be ran in the background, in detached mode
# -p exposes the app to port, maps host's port to contaier's port
```

To see the running container
```bash
docker ps -a

CONTAINER ID   IMAGE                            COMMAND           CREATED         STATUS                     PORTS     NAMES
dd8a7c1cce37   udacity-suse-python-helloworld   "python app.py"   6 seconds ago   Exited (1) 4 seconds ago             competent_gates
```
To test it, open <code>127.0.0.1:5000</code> in your browser.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te4vhq592k7ccvi2vvgr.png)

Great! Once you've tested that it's running, it's time to share it to the world. You can upload the image to your [Dockerhub](https://hub.docker.com/) account. ON your terminal, login to your account
```bash
docker login
```
Tag your docker image. The name you specify will be used as the tag when it's pushed into your repository. You should create a repository in your dockerhub account.
```bash
docker tag udacity-suse-python-helloworld edenjose/udacity-suse-helloworld:v1.0.0

# edenjose is the repository, followed by the 
# name the image will be saved with.
```
To push the image to your dockerhub account, run the command below. Specify the repository and the version.
```bash
docker push edenjose/udacity-suse-helloworld:v1.0.0
```
Go to your browser and login to your Dockerhub account. You should now see the image you pushed there.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3oyyz1w29nb4s5lcj3pu.png)

Awesome! Now everyone can pull and use the image from your repository!😺

----------

## Lab 2 - Packaging a Go application

Using the same cloned repository, we'll now package a Go application. Go to <code>exercises/go-helloworld</code> folder. Here you should see the <code>main.go</code>

```bash
ls -la
total 8
drwxr-xr-x. 2 root root  38 Jun 21 14:49 .
drwxr-xr-x. 5 root root 105 Jun 21 14:49 ..
-rw-r--r--. 1 root root 236 Jun 21 14:49 main.go
-rw-r--r--. 1 root root 283 Jun 21 14:49 README.md
```
Checking the code, you will see that the application should return a 'Hello World' message and will use port 6111

```go
package main

import (
    "fmt"
    "net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "Hello World")
}

func main() {
    http.HandleFunc("/", helloWorld)
    http.ListenAndServe(":6111", nil) 
```

Let's now build our dockerfile.

```docker
FROM golang:alpine 

WORKDIR /go/src/app

ADD . .

RUN go mod init

RUN go build -o helloworld

EXPOSE 6111

CMD ["./helloworld"]
```

Now, before building the image. Make sure that [Go is installed in your machine](https://linuxize.com/post/how-to-install-go-on-centos-7/). Once you've installed Go, you can try to run the application by issuing:
```bash
go run main.go
```

After the application is tested, you can now build the docker image. You can specify any tag you like.

```bash
docker build -t udacity-suse-helloworld-go .
```
Check if your docker image is created
```bash
go-helloworld]# docker images
REPOSITORY                         TAG          IMAGE ID       CREATED              SIZE  
udacity-suse-helloworld-go         latest       4fa5b74ed770   About a minute ago   428MB 
edenjose/udacity-suse-helloworld   v1.0.0       8ac51fb8decf   About an hour ago    894MB 
```
Run the container based on the image to test locally first. Then open the <code>127.0.0.1:61111</code> in your browser.
```bash
docker run -d -p 6111:6111 udacity-suse-helloworld-go
```

Tag the image before pushing to your DOckerhub repository.
```bash
docker tag udacity-suse-helloworld-go edenjose/udacity-suse-helloworld-go:v1.0.
```

Check the list of docker images again. Note that when you tag the docker image more than once, the image would also appear more than once when you run the command below. However, they are not duplicates, as you can see that both image will have same image ID.
```bash
docker images

REPOSITORY                            TAG          IMAGE ID       CREATED             SIZE
edenjose/udacity-suse-helloworld-go   v1.0.        4fa5b74ed770   15 minutes ago      428MB
udacity-suse-helloworld-go            latest       4fa5b74ed770   15 minutes ago      428MB
edenjose/udacity-suse-helloworld      v1.0.0       8ac51fb8decf   About an hour ago   894MB
udacity-suse-python-helloworld        latest       8ac51fb8decf   About an hour ago   894MB

```
Push the image to your dockerhub repository.
```bash
docker push edenjose/udacity-suse-helloworld-go:v1.0.
```
Checking your dockerhub account:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/66m4udy6rkergd0fk01d.png)

-------------

Great job! We've now containerized two applications and successfully pushed them to our Dockerhub repository. Up next, we'll learn how to manage containers using Kubernetes.

---
> *If you enjoy this write-up and would like to learn more, make sure to hit the* **Follow** *just below and bookmark the series. I'll also be glad to connect with you on [Twitter](https://twitter.com/eden_noel08). <br>
See you there!* 😃
____________________________________________

{% user jeden %}