# Lab 1 - Start with a Docker Image

This workshop is an introduction to Docker, which is a runtime for containers. You will create a containerized Node.js application that provides a service to translate phrases from one language to another. The application uses the IBM Watson in [IBM Language Translation service](https://www.ibm.com/watson/services/language-translator/).‌

## **Docker**

For this Lab you will use Docker.&#x20;

![The Docker architecture - containers are separated from the OS](/files/-LthwLP_WM_81c65yfLd)

{% hint style="info" %}
Docker container technology separates applications from the underlying Operating System and infrastructure, which is an analog to VM technology that is separating an operating systems from the bare metal - server hardware.&#x20;
{% endhint %}

Docker technology virtualizes the Operating System (OS), and thanks to it only the application, and specific dependencies like libraries and binaries are being packaged in the image.&#x20;

Starting such an image is much faster omitting start of an OS. In addition the image now is very portable among various host servers running the Docker engine. And since ther is no OS, there isn't its surface for security vulnerabilities connected to it.&#x20;

## **Steps**

The following steps would allow you to create the Watson translation service in the cloud. You will record the API Key to access your service later. You will create a node.js based microservice. This microservice will respond to requests with results of the translations coming from IBM Watson service. As soon as you are ready with the microservice you will be able to start Build - Ship - Run containerization process. You will build an image, and push it to a public repository - Docker Hub, and run the containerized microservice.&#x20;

![The Docker is about Building-Shipping-Running containers](/files/-Lthvuq8uvz3mrYS5g_n)

### **Step 1 - create a language translation service**

‌Open your IBM Cloud dashboard using your IBM Cloud account with this URL: : [ ](< http://ibm.biz/wwcode-sf-202003>)[**http://cloud.ibm.com**](< http://ibm.biz/2020-CFE-DEV>) .&#x20;

![Click on the Catalog tab.](/files/-LthxWLaGzjKdFOIbJSH)

Search translator to find the service. You can also find the service by navigating to the AI section on the left bar.

![Search for the "Language Translator" service](/files/-LthyE7dkUqWr8YzuWKh)

Click on the service to create a new instance. Pick the Lite **free of charge** plan on the next page and click **Create** to finish creating the service.

![Pick free of charge Lite plan and hit Create button](/files/-LthyWbVChchkF_BAAAO)

You will be redirected to the service landing page.

### **Step 2 - copy the credentials to be used later**

Click on Service Credentials on the left bar.

![Copy the "apikey" and "url" values for the future referenced](/files/-Lthypg9fN1FbyPE_G4X)

If you do not see a credential provided for you, you can create a new set of credentials. Save your **apikey** and **url values** somewhere for the next section in this workshop.

**Congratulations!** You created your first Language Translator service. The next steps will show you how to build a Docker container for a Node.js application that provides an end point to translate text!

### Step 3 - clone repository

Open your local terminal and clone the reposiotry with the example (you might want to use git, or simply download the zip file from the following location <https://github.com/IBM/docker-nodejs-language-service> ).

```
git clone https://github.com/IBM/docker-nodejs-language-service.git
cd docker-nodejs-language-service
```

### Step 4 - build the docker image

Change into the directory you just cloned and build the docker image

```
docker build -t <docker-username>/node-container .
```

The `docker-username` is required if you want to publish your image to [Dockerhub](https://hub.docker.com/).  Replace `<docker-username>` in the above command with your docker account name.

{% hint style="info" %}
*If you do not have **a Docker account** - you would need to **create one directly on hub.docker.com** - choose sign up button.*
{% endhint %}

Alternatively, you can also build directly from github using the following command without cloning the repository:

```
docker build -t <docker-username>/node-container https://github.com/IBM/docker-nodejs-language-service.git
```

This command uses the Dockerfile to download a Node.js 10 base image and then install our Express.js application on top.&#x20;

#### Dockerfile - what is there for you

Let's explore the contents of this `Dockerfile`:

`FROM node:10`  ... builds our image on top of the Node.js 10 image.&#x20;

`WORKDIR /usr/src/app`  ... creates a working directory for our application to live in.&#x20;

`COPY package*.json ./`  ... copies the package.json file to our working directory. RUN npm install ... install our dependencies. We just have two dependencies in this application: express and ibm-watson.&#x20;

`COPY . .` ... copy the rest of our source code into the docker image&#x20;

`EXPOSE 8080` ... expose port 8080. We will still have to forward our local port to this docker container port later.&#x20;

`CMD [ "node", "server.js" ]`... starts the application by running node server.js.

### Step 5 - run the docker image

```
docker run -p 8080:8080 -e lt_key=<api_key> -e lt_url="<api_url>" -d <docker-username>/node-container
```

In my case, I would run

```
docker run -p 8080:8080 -e lt_key=my-api-key -e lt_url="https://api.us-south.language-translator.watson.cloud.ibm.com/instances/somenumber" -d blumareks/node-container
```

### Step 6 - test the application

```
curl "localhost:8080/translate?text=how%20are%20you"
```

You should see output as follows:

```
{
  "translations": [
    {
      "translation": "¿Cómo estás?"
    }
  ],
  "word_count": 3,
  "character_count": 11
}%
```

{% hint style="info" %}
If the command returns error  *curl: (7) Failed to connect to localhost port 8080: Connection refused* - check logs:

```
docker logs no-of-image
```

`(in my case this command looks like this` \
`docker logs 7f72ca211fffbf8de355b53e197e9213ecc5481e0b6045f82b420dcbb0a4e78e`\
If the log says: *Identifier 'PORT' has already been declared*\
you might want to comment the offending line. Edit it with vi:\
`vim server.js`\
add comment, ie. **//** before start of line 11, it should look like this:\
`//const PORT = process.env.PORT || 3000;`

In addition you might want to stop and delete the image, then rebuild it - going back to step 4. Ask your instructor if you have any issues with that. Use the following commands:

```
docker container stop no-of-image
docker container rm no-of-image
```

{% endhint %}

The text is translated to Spanish `(en-sp)` by default. You can specify the langauge by passing in the lang flag as follows:

```
curl "localhost:8080/translate?text=how%20are%20you?&lang=en-de"
```

You should now see the same text translated to German:

```
{
  "translations": [
    {
      "translation": "Wie geht es Ihnen?"
    }
  ],
  "word_count": 3,
  "character_count": 12
}
```

Another example ...

```
curl "localhost:8080/translate?text=People+are+suffering.+People+are+dying+and+dying+ecosystems+are+collapsing.+We+are+in+the+beginning+of+a+mass+extinction%2C+and+all+you+can+talk+about+is+the+money+and+fairy+tales+of+eternal+economic+growth"


{
  "translations": [
    {
      "translation": "La gente está sufriendo. La gente está muriendo y los ecosistemas moribundos se están derrumbando. Estamos en el principio de una extinción masiva, y todo lo que se puede hablar es el dinero y los cuentos de hadas del crecimiento económico eterno"
    }
  ],
  "word_count": 39,
  "character_count": 204
}
```

in Polish

```
curl "localhost:8080/translate?text=People+are+suffering.+People+are+dying+and+dying+ecosystems+are+collapsing.+We+are+in+the+beginning+of+a+mass+extinction%2C+and+all+you+can+talk+about+is+the+money+and+fairy+tales+of+eternal+economic+growth&lang=en-pl"
{
  "translations": [
    {
      "translation": "Ludzie cierpią. Ludzie umierają, a umierające ekosystemy się zapadają. Jesteśmy na początku masowego wyginięcia, a wszystko, o czym można rozmawiać, to pieniądze i bajki o wiecznym wzroście gospodarczym"
    }
  ],
  "word_count": 39,
  "character_count": 204
}
```

You can see the supported languages `(both from and to)` in the [Language Translator documentation](https://cloud.ibm.com/docs/services/language-translator?topic=language-translator-translation-models).

**Congratulations!** You just containerized a Node.js application that provides transation services.

## Clean up

### Step 7 - stop the container

You can first stop the container. You need the container tag or the id to stop it. Let's look it up first

```
docker ps | grep node-container

419104eff9be        blumareks/node-container                           "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes                       0.0.0.0:8080->8080/tcp                            cranky_davinci
```

In my case, the container is called `cranky_davinci` and has an id of `419104eff9be`.

Stop the image with the following command. You can replace the id with your container id.

```
docker container stop 419104eff9be
```

### Step 8 - remove the container

Run the following command to remove the container. Replace the id with your container id identified in the step above.

```
docker container rm 419104eff9be
```

### Step 9 - remove the image

You can now delete the image. You again need the image id.

```
$ docker images | grep node-container
blumareks/node-container                       latest                         8baa6ca9cdac        5 minutes ago       958MB
```

Now, delete the image as follows.

```
$ docker image rm 8baa6ca9cdac
Untagged: blumareks/node-container:latest
Deleted: sha256:8baa6ca9cdac8868d8e17642e90b433c7aa588a615b59ac9b528fb8635698a6e
Deleted: sha256:8c279f530b3ff260279f9cb8d22d167d748e53df4f6eab91b089b6c90b4da9f2
Deleted: sha256:9845fb86e05aa69c677dc999b6bbdeceafc460e70604092e0247e0f8880ec93e
Deleted: sha256:84ea0148452752e2aba0a1e1ef963355781a3fb87e485e9a440e8e8fc002d045
Deleted: sha256:f4f99031ae0d1cf0079d9981ef6e8dff2231eff670ac7ea4a4f27472282d7ad2
Deleted: sha256:bf579e37b35bb7b20ed0cb3140220118cbbd1d0564a512f21868568b3683a392
Deleted: sha256:07b958722eb2513e88186b2f6eddadcec0b8772001a598244352073ac5caf176
Deleted: sha256:361c46840912a7b9539b6ddf00164492fc594701085f0e2c9d2c1544bca8498c
```

## Troubleshooting

### Check container logs

You can check the logs for your container using

```
docker logs <container_id>
```

For example ...

```
root@terminal-5-846448d675-bk75j:/data# docker logs 4450279a9f50   


Running on http://0.0.0.0:8080
No language passed to translate to. Converting to Spanish by default.
{
  "translations": [
    {
      "translation": "Hola"
    }
  ],
  "word_count": 1,
  "character_count": 5
}
```

**Congratulations** again on creating your first docker container that hosts a Natural Language Translation service!&#x20;

## **Next steps**

In order to read and learn more about Docker - please use this link: <http://blumareks.blogspot.com/2019/09/basic-docker-functionality-containers.html>​

Please claim your pre-provisioned cluster, and set up your environment for the next labs.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ibmdevelopersf.gitbook.io/red-hat-worldtour/lab-1-start-with-a-docker-image-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
