Trouble at the docks - part 1
Tags: programming, tutorial, docker, devops
Published: 2023-01-24 14:20:05


![docks](https://images.unsplash.com/photo-1591907303049-a5e5df26bcb9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1207&q=80, "docks")

So you have written your code and you are feeling pretty proud about it and want to share it with your friends.

They pull the code from your github repo but something is not working right. Maybe it's because you have written all the code on Windows and your friends are using Linux. What should you do? Should you bring your computer to them and show them just how great your code is? 

They live in Guadalajara and it would be nice to visit them but the plain ticket is pretty expensive and they are not that good of a friend.

One day you hear a rumor that there are some people by the docks who deal with these type of situations. These people are pretty dangerous, but you are brave aren't you? I mean, sometimes you go the the restaurant on your own. If that's not bravery than what is? 

On a dark night you finally get up the courage to go to the docks. There don Porto awaits you. 

### Don Porto

Who's there? - a deep voice asks

_Itttt-s me. I-iii came becuase I heard you can solve my problems._

Oh, yeah? What problems do you have? And how much money you got? 

_I need you to transfer some code for me. I have developed an 
application but my friend can't run it on his computer._

Well, maybe you need a new friend. And what about my money?? 

_I do not have any money. My mom told me that people are valued by what's inside their hearts not by what's inisde their wallet._ 

Your mom was messing with you. Ok since you do not have any money you will have to load the cargo by yourself. My crew will then ship it. 

_But I don't know how to operate the forklift. I have never worked on the docks._

Yes I can see that by your gentle hands. Don't worry you won't be needing any of that. Where is your code? 

_I have it on github. Let's clone it._

```
git clone https://github.com/veronika-simic/dev_docker_part1.git
```

Huh, and here I thought you are some kind of a genius. Let's start I haven't got all night.

_What are you going to do? I don't wan't anyone to get hurt._

I am going to **dockerize** your code.


## The secret  

This secret has been passed down in my family for many generations. The secret called **Docker**.

_What a weird family. Go on..._

Well, Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called **containers**. Containers have everything a software needs to run including libraries, system tools, code, and runtime. With it you can quickly deploy and scale applications into any environment and know your code will run. Basically what Docker does is it makes really easy to install and run software without you troubling your little head with setup or dependencies.
 
_Well that sounds as exactly what I need. And my head is pretty small. Where are these containers?_

Not very patient are you? Containers are not physical constructions. They are an instance of an **image**. We will start by creating a new file in your project called **Dockerfile**. Without any extensions. Everything starts with the Dockerfile. 

_Huh, not a very catchy name._

Nobody cares for your comments. Here put this code iniside the new file called Dockerfile.

```
FROM node:16-alpine

RUN npm install

CMD ["npm", "start"]
```

_Ok what now? Is this a container? Can I go home now to my cat?_

No. Fluffy will have to wait. This is just a baseline for our image which we are going to later send to your "friends". Then they can create a container out of it and run this very complicated code of yours. 

_What is an image? And what does all of this code do? And how do you know my cat's name?_

Oh I have to explain everything to you... You are one of those people. When I say an image what I actually mean is a **file system snapshot**. An image is a physical file which contains directions and metadata to build a specific container. It has all the files and folders you have specified in your project. After you build the image you can redistribute it using the registry. The registry is like a Git repository you can push and pull images. Images can then be used to run containers. And you have your cats name tattooed on your forehead. 

_Wait, what?_

Ok baby steps it is. Let's say you run Chrome on your computer. What happens is it calls the OS which then calls kernel and says: Hey I want to run this program. The kernel runs the files from your hard disk and you can now spy on your ex. Good for you. Imagine that Chrome uses Pyhton version 3 and Spotify uses Python version 2. What now? Does this mean that you can't at the same time spy on your ex and cry while you listen to "Everybody hurts"? 

_Have you been watching me?_

Just a lucky guess. In order to make this possible, you need to use an operating system feature known as namespacing. A namespace is a feature which gives you the opportunity to isolate processes, hard drive, network, users, hostnames and so on. Now you can do both. 

_Aha so we are going to make use of namespacing?_

Hey there might be some future for you. Yes, containers use namespaceing so we can provide isolation for running processes, limiting their access to system resources without the running process being aware of the limitations. It also means that docker images and containers are pretty small in size. So they are faster to run and install. Let's get back to our code. Build the image  by running this command in terminal window: 
 
`docker build .`

_Hey but I get an error. What's going on? Are you trying to trick me?_

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pplzxr5rpeqlud5t6s2g.png)

The error you see is due to the fact that our temporary image built from node:16-alpine does not have it's own package.json. We have to copy it to the container.
We can do that by adding `COPY . .` statement to our Dockerfile.

```
FROM node:16-alpine

RUN npm install
COPY . .

CMD ["npm", "start"]
```

What are you doing? You can't run npm install before copying package.json. Put the COPY statement before the RUN.

_Sorry, sorry. All this fish smell is making me dizzy._

```
FROM node:16-alpine

COPY . .
RUN npm install

CMD ["npm", "start"]
```

Great now everything is going to be copied from our project directory to containers directory. Now build the image again. 

![build image terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftt1wd4p6skvvgtnfy0v.png)

_Ah, ok now it works. But what if my folder has the same name as the folder inside the container? I do not want to override it._

Aha. We can avoid this by specifiying the name of the folder we want in container. Then everything gets copied into that container. This container is by convenction called app.

_Can we name it Fluffy though?_

No.
 
```
FROM node:16-alpine

WORKDIR '/app'
COPY . .
RUN npm install

CMD ["npm", "start"]
```

_So now everything is in this folder called app? How great! Let me build my image again. Can I name my image?_

If you must. What would you like to name your image? 

_Masterpiece definitely. I mean have you seen what this code does?_

Yes, I can't unsee it. Ok let's do that by running this command in terminal: 

`docker build -t masterpiece .`

![masterpiece built](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89jeswbeo4y033asxy6h.png)

As you can see we have built your "masterpiece". The next step is to run the docker image. That way we create a container from our image. Remember container is a process that is running based on the files provided by the image. 
Run this command in terminal:

`docker run -p 3000:3000 masterpiece`

![running container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z31ncywpqdaarawtqvk2.png)

_Yes my container is running. Does the script start immediately because of the_ `CMD ["npm", "start"]?` _And what is this weird command doing?_

Well, what's happening currently when you run your app is that any call to localhost:3000 doesn't get redirected to your container. In order for us to achive that we had to use **port mapping**.
And yes, our script starts immediately because of the last command in our Dockerfile. There you can specify any command you want to use to start your script.

_So what we are doing is saying to our server hey, any call that goes to localhost:3000 redirect it to my conatiner's port 3000? Can I specify any port number?_

That's right. You can specify any port you want in the docker container. Just make sure that the port on your local machine is not already taken by some other application. 

_Ok what's next now that my container is running? How do I send it to my friend? And what about all the output in the console? What's going on there? And what if I decide to change something in my code? Do I have to rebuild my image again and again?_

I see you are very interested in all of this. Unfortunately, I have to go take care of someone.

_Aha ok. Then next time. Sorry did you say someone?_

No, no. I meant something. Say hello to Fluffy. :cat: