Skip to content
/ rest-api Public template

Production-ready REST API with Docker, Hashicorp Packer, custom error handlers and ES7+ support

License

Notifications You must be signed in to change notification settings

sydrawat01/rest-api

Repository files navigation

REST API

Unit Tests Packer AMI template validation Build Release

This is a basic skeleton code to create a basic REST API using NodeJS, ExpressJS and Babel.

Note

NOTE: Please note that this is still a work in progress.

Features

  • ES7+
  • NodeJS
  • ExpressJS
  • Winston for logging
  • Basic test scripts
  • Custom error handlers
  • PostgreSQL and Sequelize
  • Bcrypt
  • Custom Amazon Machine Image using Hashicorp Packer
  • Containerization using Docker

Planned features

  • AWS S3, DynamoDB and SNS Topics
  • Email verification of user
  • TypeScript support

Connect to local db

psql postgres

CREATE ROLE me WITH LOGIN PASSWORD 'password';
ALTER ROLE me CREATEDB;

psql -d postgres -U me

CREATE DATABASE test;

\c test

select * from users;

Docker

This is an example repository that will help you dockerize your Node+Express application using Docker.

  1. Create a simple REST API with the following endpoints:
  • / that returns OK status code (200)
  • /health that returns OK status code(200)
  1. Create a simple test that checks the health routes.

  2. Create a new file named Dockerfile at the root of the repository.

  3. Add the following configuration to the above created file:

# which node to use for your container
FROM node:alpine

# the directory where the appication will be copied to in your container
WORKDIR /usr/src/app

# copy the contents of the base(app) directory to the container WORKDIR
COPY . .

# commands to run to install dependencies
RUN npm install

# port that must be exposed to the client where the application is running in the container
EXPOSE 3000

# command to start the application in the container
CMD ["yarn", "start"]
  1. Now, to create an image of your basic REST API:
# -t option to tag the image with a version
# if a version is not provided, the default tag is 'latest'
# the '.' option at the end is to build the current working directory
docker build -t <image-name>:<image-version> .

Example:

docker build -t api:v1 .

To create a docker image using another version of a Dockerfile, use the following command:

docker build -t <image-name>:<image-version> -f <Dockerfile-name> .

Example:

docker build -t api:v2 -f Dockerfile.dev .
  1. To verify your image is build and ready:
# lists all images that docker has built or pulled from docker hub
docker images
  1. To create and run a container:
# -ti is to run the container in an interactive terminal mode
# --name is to name your container
# -p is to expose the port from the container to the local machine where the container is running
docker run -ti --name <container-name> \
-p <local-machine-port>:<container-port> \
<image-name>:<image-version>

Example:

docker run -ti --name rest-api-container -p 3000:1337 api:v1
  1. Test the API endpoints using Postman on http://localhost:3000.

  2. To stop a running container:

docker container stop <container-name>

Example:

docker container stop gpt-container
  1. To restart a stopped container:
docker container start <container-name>

Example:

docker container start gpt-container

To enter the bash terminal within the container:

docker exec -ti <container-name> bash

Example:

docker exec -ti gpt-container bash

Docker bind mount

The -v flag represents the volume in our container, where our application will be uploaded in the Docker Ubuntu image.

docker run --name <container-name> \
-p <local-machine-port>:<container-port> \
-v <local-machine-dir>:<container-WORKDIR-PATH> \
<image-name>:<image-version>

Example:

docker run --name rest-api-container-2 \
-p 3000:1337 \
-v $(pwd):/usr/src/app \
api:v1

NOTE: If you are on a windows computer, $(pwd) will not work. Instead, use %cd%.

Anonymous volume

To leave the node_modules directory untouched in the local machine directory, and to not track it in the docker container, we use anonymous volumes.

docker run --name <container-name> \
-p <local-machine-port>:<container-port> \
-v <local-machine-dir>:<container-WORKDIR-PATH> \
-v <container-WORKDIR/node_modules> \
<image-name>:<image-version>

Example:

docker run --name rest-api-container-3
-p 3000:1337 \
-v $(pwd):/usr/src/app \
-v /usr/src/app/node_modules \
api:v1

Since we do not have the : colon to link this volume in our container to the local machine directory, this is an anonymous volume.

SSH into a container

docker exec -ti <container-name> /bin/sh

Example:

docker exec -ti rest-api-container-3 /bin/sh

Stop and delete containers

  1. Look for the container name:
docker ps
  1. Stop the container using the container name:
docker stop <container-name>

Example:

╰─ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                    NAMES
15fa4c6bbd11   api:v2    "docker-entrypoint.s…"   8 seconds ago   Up 6 seconds   0.0.0.0:3000->1337/tcp   rest-api
docker stop rest-api
  1. To check for stopped containers:
docker ps -a
  1. Make sure that the container is stopped, then proceed to remove that container.
docker ps;
docker rm <container-name>

Example:

docker rm rest-api

Delete docker images

To delete docker images:

  1. Check the name of the image you want to delete:
docker images
  1. Delete the image by it's name:
docker image rm <image-name>:<image-version>

Example:

# check for docker images
docker images
# output
╰─ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
api          v3        4d74db3e5ada   7 hours ago   366MB
api          v2        7bc302778f7c   7 hours ago   366MB
# remove the desired docker image
docker image rm api:v2

Work in progress

Do not build .env into the docker image.

Author

Siddharth Rawat

License

MIT License