How to deploy a node.js app to digital ocean using Docker
Tags: docker, devops, node, webdev
Published: 2021-10-30 12:29:59

In this article I'm going to assume you have a working Node js app locally. In a terminal you type in `npm start` and whoosh we have a working node app locally. However how do you deploy it to the internet? 

You could use Platforms as a Service (PAAS) sites like Heroku and you can link your github repo to Heroku and deploy from there. At the time of writing that costs $7/month (roughly £5/month)

But there is a more Devops pro like way which may be more customisable. 

Digital Ocean (the lowest version is $5/month or £3.65 /month) which also offers a PAAS or Infrastructure as a service (IAAS). 
Digital Ocean [Sign up here](https://m.do.co/c/b6731a07428c)

You can pay per month to run your code on one of their private virtual servers which they call 'Droplets'. Hence the digital _ocean_... 

**Update Feb 2023**
Digital ocean now has a feature that is similar to Heroku and you can link your github repo.

## Getting started
Now to get started, let's set up a Docker Hub account [here](https://hub.docker.com/signup). 
You'll need to provide: 
* a Docker ID (username) 
* an email address
* password

Think of Docker Hub as a GitHub for Docker images. You can create a repository to store an image (a snapshot of your code environment). Create a repository and come up with a name which I will refer to as 'DOCKER-REPO'. And you can set it as private or public. I have set mine as private. 

You can also install Docker Hub for Windows/ Mac (There was a link on the main dashboard to do so.) 

### So what have we just created?
1. A Docker Hub account
2. A repository to store docker images
3. Downloaded Docker Desktop to view running docker images locally

## Setting up docker locally

Create a file name **Dockerfile** in the root of your project. And add in this code:
```
FROM node:13-alpine

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000
CMD [ "npm", "start" ]
```
This code is:
1. Getting the node:13-alpine image as a template
2. Telling docker which directory to work with
3. Copying our package.json and package-lock.json
4. Running `npm install` on Docker
5. Coping the code into the image, exposing port 3000 and running `npm start`.

We have now created a file that can be run by docker.

We can then run the following command and changing **<YOUR_APP_NAME>** to a name of your choice.
`docker build . -t <YOUR_APP_NAME>`
This will build the docker image. You will be able to see it when you open up your docker hub application.

You can now run `docker run -p 3000:3000 <YOUR_APP_NAME>` (again using your app name instead of **<YOUR_APP_NAME>**) and this will expose the 3000 port to run at 'http://localhost:3000'. 

Check it out. Does the node app work like when you run `npm start` before setting up docker? Brilliant! It's now running in a Docker container.

### So what have we just done?
* Created a Docker file which outlines the Docker image we want to create
* Built a docker image using `docker build . -t <YOUR_APP_NAME>`
* Ran the docker image in a container using `docker run -p 3000:3000 <YOUR_APP_NAME>`.
* Checked that the app works at 'http://localhost:3000'.

## Push to Docker Hub
This is brilliant. We have a Docker image running locally so now lets push it to a repository like we do with our code on GitHub/ GitLab etc. 

First let's tag the image with the following command:
`docker tag <YOUR_APP_NAME> <USER_NAME>/<DOCKER-REPO>:1.0`
Replace the following:
* **<YOUR_APP_NAME>** with your app name
* **<USER_NAME>** docker id that you chose when you setup docker hub.
* **<DOCKER-REPO>** with the name of the docker hub repo that you created previously.

Next, before we push to the Docker hub repo we will need to login with `docker login`. You can input your docker id (username) and password. Notice that there is no visual output when typing in your password.

Then once that is successful run `docker push <USER_NAME>/<DOCKER-REPO>:1.0`

You should now see the docker image on your docker hub repo. 

### What have we just done? 
* Tagged a docker image 
* Shared the docker image with docker hub to be used later on digital ocean.

We are now ready to deploy the Docker image to Digital ocean!!! 🎉🎉

## Deploy to Digital Ocean

This maybe the bit you really came for. I will tell you now that there is a cost involved here. With this link [https://m.do.co/c/b6731a07428c](https://m.do.co/c/b6731a07428c)  you can get $200 dollars of **FREE** credit on Digital Ocean so that you can test out your ideas for 60 days. 

So firstly you'll need to create a Digital Ocean account [here](https://m.do.co/c/b6731a07428c). When I set up I was required to pay $5 which will be used as credit for your first droplet and to verify your identity. 

## SSH keys
First thing we need to do is add an public ssh key to be able to access our droplets later. So please open up a terminal and type in `ssh-keygen -t rsa -b 4096`. This will create a ssh key for us to use. Use the default name and if you want to you can include a passphrase for extra security.

You have just created a public ssh key (id_rsa.pub) and secret key (id_rsa). The private should never EVER be shared. If you used the default name the files will have been saved in a folder `~/.ssh`. 
Notice the . in front of the ssh? This is because it's a hidden folder so that will be why you can't see the folder in the File explorer on windows and Finder for Mac. So in your terminal navigate back to your root with `cd ~/.ssh` and if you run `ls -la` you will see 2 files- id_rsa and id_rsa.pub. 

To view the PUBLIC key you can run `cat id_rsa.pub`. This will output the file and you can copy this to use on digital ocean.

Login to Digital Ocean and click on settings on the left hand side. Then the security tab and add the PUBLIC SSH key (the result from `cat id_rsa.pub`) in the big box and then assign it a name.  

## Digital Ocean Droplet
Now we have that set up we can create a virtual server which Digital Ocean names droplets. This can be done by selecting the 'manage' button the left hand menu and click on 'droplets' and then click 'create a droplet'.

Click on the marketplace tab (above the Linux distributions) and select the Docker setup. Then choose a Basic plan ($5/ £3.65) and in the Authentication section choose the SSH key you created earlier. 
Then click 'Create droplet'.

You have created a droplet! You have a virtual server. 

Open up a terminal on your computer and run `ssh root@<DOCKER_IP_ADDRESS>`. Replace **<DOCKER_IP_ADDRESS>** with the IP address of the droplet. 
This will allow you to ssh into the virtual server as the root.

Once you are in you can run `docker run -p 3000:3000 <USER_NAME>/<DOCKER-REPO>:1.0`. 
Replace:
* **USER_NAME** with your docker hub id
* **DOCKER-REPO** with the name of your docker hub repo.

This is running the docker image inside your droplet.
 
You will now be able to see the app running at `<IP_ADDRESS>:3000`. Replacing <IP_ADDRESS> with the droplets IP address which is found at the top of the digital ocean page.

You have now deployed your app to a droplet.
 
### What have we done?
* Created an SSH key
* Added the SSH to Digital Ocean
* Create a Digital Ocean Droplet
* SSH into your droplet
* Run docker inside your droplet

## What now?

Well as promised, if you use [https://m.do.co/c/b6731a07428c](https://m.do.co/c/b6731a07428c) you can get $200 of free credit. This will allow you to run the app and test out config without worrying that you will have to pay. 
After the 60 days you will pay the $5/£3.65 a month as the Basic plan. If this tutorial is just you testing it out remember to destroy your droplet afterwards (NOT shutdown) as you don't want to be charged. 

Thank you for reading! 

Enjoy!

To say thank you, you could buy me a coffee?

[![Buy Me A Coffee](https://cdn.buymeacoffee.com/buttons/default-black.png)](https://www.buymeacoffee.com/lukeecart)

This article contains a referral link [https://m.do.co/c/b6731a07428c](https://m.do.co/c/b6731a07428c) which can be used to get $200 free credit.

Photo by <a href="https://unsplash.com/@wocintechchat?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Christina @ wocintechchat.com</a> on <a href="https://unsplash.com/s/photos/servers?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>