Skip to content
Permalink
Browse files
added heroku docker instructions
  • Loading branch information
aa7401 committed Nov 17, 2018
1 parent 3cc9b60 commit 403d00b7760ff6a2cf452377a2fd102e86a5711f
Showing 1 changed file with 88 additions and 155 deletions.
@@ -1,79 +1,17 @@

# Docker and Deployment

In this lab you will be using Docker to deploy an API, initially to a local server and then to the cloud.

Resources:

1. [Lecture slides](https://drive.google.com/open?id=1FMZmpSx_GyIZ-os_A0eixXd-_dMybXlqY-sAWK05KiQ)

## Installing Docker on Linux

```shell
wget -qO- https://get.docker.com/ | sh
curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
curl -L https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine && \
chmod +x /usr/local/bin/docker-machine
add-apt-repository "deb http://download.virtualbox.org/virtualbox/debian vivid contrib"
wget -q http:/sudo apt-get install virtualbox-5.0/download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -
sudo apt-get install virtualbox-5.0
```

## A Local Development Environment

```shell
docker-machine create --driver virtualbox dev
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env develop
docker-machine env dev
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/home/marktyers/.docker/machine/machines/develop"
export DOCKER_MACHINE_NAME="develop"
# Run this command to configure your shell:
# eval "$(docker-machine env develop)"
eval "$(docker-machine env develop)"
```

## Docker Machines
## 1 Installation

The eval command assigns the correct values to the system variables
configures the shell to talk to our new server.
Makes the server active.
It will be the target of any docker and docker-compose commands.
We can check this has worked.
docker-machine ls
Before you start this lab you need to make sure you have Docker CE (community edition) installed and running. There are detailed instructions for [Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) [MacOS](https://docs.docker.com/docker-for-mac/install/) and [Windows](https://docs.docker.com/docker-for-windows/install/). There are also instructions for a number of other Linux distros.

## Docker Machine Commands

```shell
docker-machine active
docker-machine ip dev
docker-machine inspect dev
docker-machine config develop
docker-machine ssh dev (type exit to quit)
docker-machine stop dev
docker-machine ls
docker-machine start dev
```

## Base Images

Every custom image needs to start from a base image.
Hundreds to choose from
https://hub.docker.com/explore/
We will be building an API using NodeJS
Makes sense to use the official NodeJS image.
The latest named version is 5.9.0 (wheezy)
https://hub.docker.com/_/node/

## Getting Started with Docker on MacOS

Start by installing [Docker for MacOS](https://docs.docker.com/docker-for-mac/install/) and make sure it is running and you have logged in.

Check the versions of the installed tools:
The installation process will install three commands. Once you have completed the installation you can check that these are installed and the version you are using:

```shell
$ docker --version
@@ -84,144 +22,139 @@ $ docker-machine --version
docker-machine version 0.15.0, build b48dc28d
```

Now we can check the system is set up correctly by creating a hello world container and running it using the `$ docker run hello-world` command.
## 2 Dockerfiles

### Creating a Simple Web Server
In this part of the lab you will be learning how to auto build and deploy a nodeJS app using a Dockerfile. Start by navigating to the `exercises/07_docker/01_dockerfile/` directory. Notice that this is the standard todo web app. You will also see two extra files:

1. the `Dockerfile` contains the build script. Study this carefully, noting the build steps.
2. the `.dockerignore` file lists the files we don't want transferring to our docker container. In our instance we don't want to upload the contents of the `node_modules/` directory.

```shell
$ docker run -d -p 80:80 --name webserver nginx
$ docker build -t todo .
$ docker image ls -a
$ docker run --name todo-live -p 88:8080 -d todo
$ docker container ls -a
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
6fd6a80fb4ae todo "npm start" Up 4 seconds 0.0.0.0:88->8080/tcp todo-live
```

View the details on the container while your web server is running
you can now access the todo app on http://localhost:88

```shell
$ docker container ls
```
### 2.1 Redeploying a Container

Stop and remove the container and the image it is based on:
When changes are made to your application we need to redeploy the entire container. Since each step in the build process created an interim image, the build can skip over any steps that have not changed. In this case, the first step that is changed is where we copy over the files (since these were edited). Once the build finds a changed step it has to rebuild from this point. This is why we copied over the manifest files and installed the dependencies before we copied over the rest of the files.

The process of building and redeploying the new container is:

1. Stop the running container
2. Delete this container
3. Build the new container
4. Deploy the container
5. Remove (prune) any unused image files

```shell
$ docker container ls -a
$ docker container stop webserver
$ docker stop todo-live
$ docker container ls -a
$ docker container rm webserver
$ CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
6fd6a80fb4ae todo "npm start" Exited (0) 0.0.0.0:88->8080/tcp todo-live
$ docker rm $(docker ps -a -q)
$ docker build -t todo .
$ docker run --name todo-live -p 88:8080 -d todo
$ docker image ls
$ docker image rm nginx
$ docker image prune -f
```

Images and containers can be referenced either by their name (if this is set) or by their id. Images are used to build containers and can only be deleted if they are no longer being used. The `-a` flag is used to display containers even if they are stopped.

Try deleting all the containers (running or stopped) then delete all the images.

## Dockerfiles

In this part of the lab you will be learning how to auto build and deploy a nodeJS app using a Dockerfile. Start by navigating to the `exercises/07_docker/01_dockerfile/` directory. Notice that this is the standard todo web app. You will also see two extra files:

1. the `Dockerfile` contains the build script.
2. the `.dockerignore` file lists the files we don't want transferring to our docker container.
Since this is such a common task you might want to write a shell script to automate the process or simply chain the commands together. There are a couple of steps we can remove so there are now only 4 steps:

```shell
$ docker build -t todo .
$ docker image ls -a
$ docker run -p 80:8080 -d todo
$ docker container ls
$ docker image prune -f
$ docker rm -f $(docker ps -a -q)
$ docker run --name todo-live -p 88:8080 -d todo
```

In this case we can see that we need to access our server on port 32771. If you go to localhost:32771 you will see the running web app.

Add a few items then view the container logs, substituting the container id. If you use the `--follow` flag you get to see the live logs. press ctrl+c to quit:
### 2.2 Interacting with Docker Containers

```shell
docker logs f9ba292ca037
$ docker logs --follow f9ba292ca037
```
In this section you will be connecting to the running container. This will allow you to debug your code by displaying the information you would normally see in the terminal.

### Cleaning Up
1. Run the `docker logs todo-live` command to see the buffered terminal information.
2. If we add the `-f` or `--follow` flag we can see the live data.
1. Run the `docker logs -f todo-live` command.
2. Try adding items to the list using the website.
3. Notice what is displayed in the terminal window.
3. The `docker exec COMMAND` command allows you to run a command in a live container. If you want to connect to the bash shell you need to provide some additional arguments:
1. The `-i` or `--interactive` flag keeps `stdin` open.
2. The `-t` or `--tty` flag allocates a _pseudo terminal_.
3. If we want to run the _bash shell_ we pass this as the command.
4. So to log in and use the _bash shell_ we run the `docker exec -it todo-live /bin/bash` command.
1. To log out we run `exit`.

To redeploy the app in the container we need to stop and remove all the running containers then do a fresh build and deploy:
### 2.3 Test Your Understanding

```shell
$ docker rm -f $(docker ps -a -q) && docker build -t todo . && docker run -p 80:8080 -d todo
```
1. Improve the appearance of the web page by adding an external stylesheet.
2. Redeploy the app to see the improvements.
3. Live monitor the logs and try adding and removing items.

The `docker image prune -f` command deletes all dangling images (ones not currently being used by a container).
## 3 Deploying to the Cloud

## Deploy to Heroku
Now we have the image runnign in a container on a local virtual machine (VM) we should be able to deploy it to the cloud. In this tutorial you will be deploying to [Heroku](https://heroku.com) which provides hosting for up to 5 docker containers for free. Make sure you have an account and are logged into the dashboard.

Install the Heroku CLI tools:
Deployment will make use of the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) which should be downloaded and installed.

- Mac: `brew install heroku/brew/heroku`
- Linux: `wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh`
We atart by using this tool to log into Heroku. We can then containerise and push our Docker image to the cloud. For the application name include your username.

Log in using the `heroku login` command:
The first time it needs to upload all the docker images including the intermediate ones but for future updates it only needs to start uploading from the point where the image has changed. This makes it critical to design your `Dockerfile` in the optimal sequence with the parts that are likely to change towards the end of the script.

```shell
$ heroku login
Enter your Heroku credentials:
Email: johndoe@gmail.com
Password: *********
Logged in as johndoe@gmail.com
$ heroku create johndoe-docker
Creating ⬢ johndoe-docker... done
https://johndoe-docker.herokuapp.com/ | https://git.heroku.com/johndoe-docker.git
$ heroku auth:token
$ docker login --username=_ --password=e014b137-4166-4e1c-8714-047ba6954e4f registry.heroku.com
$ heroku container:login
$ docker build -t registry.heroku.com/marktyers-docker/web .
$ docker push registry.heroku.com/marktyers-docker/web
$ heroku container:release -a johndoe-docker web
Releasing images web to johndoe-docker... done
$ heroku open -a johndoe-docker
```

Next you need to generate an auth token:
If you experiece any issues you can SSH into a running container on Heroku using `heroku run bash -a johndoe-docker`, substituting your heroku app name. To close the SSH connection you use the `exit` command.

```shell
$ heroku auth:token
› Warning: token will expire 11/10/2019
› Use heroku authorizations:create to generate a long-term token
c845f5b3-bad1-4dbb-8c78-1211df77221c
$ heroku run bash -a marktyers-docker
Running bash on ⬢ johndoe-docker... up, run.4098 (Free)
~ $ exit
$
```

Once you have these you can use the docker commands on any machine to push your container. Start by loggin in with docker. Both the commands below are equivalent but the second will prompt you for the token:
## 4 Deployment Using SFTP

```shell
$ docker login --username=_ --password=c845f5b3-bad1-4dbb-8c78-1211df77221c registry.heroku.com
$ docker login --username=_ --password=stdin registry.heroku.com
$ heroku container:login
$ docker build -t registry.heroku.com/marktyers-todo/web .
$ docker push registry.heroku.com/marktyers-todo/web
sftp -i /path/to/private/keyfile user@remoteaddress
```
https://medium.com/travis-on-docker/how-to-run-dockerized-apps-on-heroku-and-its-pretty-great-76e07e610e22

### Better Way to Push to Heroku
## 5 Deployment Using RSync

This requires the installation of the Heroku CLI tools:
## 6 Deployment Using Git

- Mac: `brew install heroku/brew/heroku`
- Linux: `wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh`
When you create a new Heroku instance it automatically installs a headless version of git and configures the appropriate git hook (`post-receive`). Heroku provides the appropriate remote URL in the terminal so all you need to do is add this as a new remote and push.

Log in using the `heroku login` command:
The `heroku open` command opens the app in your default browser.

```shell
$ heroku login
Enter your Heroku credentials:
Email: johndoe@gmail.com
Password: *********
Logged in as johndoe@gmail.com
$ heroku create johndoe-git
$ git push heroku master
$ heroku open
$ heroku run bash
```

```shell
$ heroku create
Creating app... done, ⬢ intense-sands-59437
https://intense-sands-59437.herokuapp.com/ | https://git.heroku.com/intense-sands-59437.git
$ heroku container:push -a intense-sands-59437 web
Building web (/Users/marktyers/Downloads/docker-node-app-master/Dockerfile)
Sending build context to Docker daemon 9.216kB
...
$ heroku container:release -a intense-sands-59437 web
Releasing images web to intense-sands-59437... done
```

### SSH into a Container

get a list of running containers using `docker ps`. In the examples below it is assumed the container is called `todo-app`.

```shell
$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NAMES
50074f650cdd todo "node index.js" 0.0.0.0:80->8080/tcp todo-app
$ docker exec -it todo-app /bin/bash
root@50074f650cdd:/usr/src/app#
```
### 6.1 Deploying Directly From GitHub

You can SSH into a running container on Heroku using `heroku run bash -a marktyers-todo`, substituting your heroku app name.
https://medium.freecodecamp.org/how-to-deploy-a-nodejs-app-to-heroku-from-github-without-installing-heroku-on-your-machine-433bec770efe

0 comments on commit 403d00b

Please sign in to comment.