Every application we develop rely on several dependencies like platform, database, tooling and technology. Most of my applications require NodeJS, MongoDB and Redis along with NPM to run. We all have installed our favourite software on our machines and we love to use them in most of our applications.
But have you ever face any challenges to having the same software in other environments and machines like dev, beta or production or may some of our co-developers who are working with us on the same application?
Well, most of the time they all have their favourite software installed with the specific versions they like and keeping them in sync is nearly impossible.
Docker is the answer to all questions related to software dependencies for application to develop, test and deploy applications faster.
As per Wikipedia
Docker is a computer program that performs operating-system-level virtualization, also known as “containerization”. It was first released in 2013 and is developed by Docker, Inc. Docker is used to run software packages called “containers”.
In a simple word, Docker is a platform help you to package your application and all its dependencies in a container and ensure that your application runs on any platform or machine.
A Dockerfile
is a plain text document containing all the required step by step commands to test, build or run the application.
docker-compose.yml
A docker-compose.yml
is a YML file containing the required configuration for each container in the multi-container Docker environment.
In our below example we will be using both to build and run our application.
To install docker on your machine follow the below links
For more details visit https://docs.docker.com/
To get started, let's define the core dependencies we will be needing for our next awesome application.
version: '3'
services:
myapp:
container_name: myapp
restart: always
build: .
ports:
- '4300:4300'
- '4301:4301'
links:
- redis
- mongo
mongo:
container_name: myapp-mongo
image: 'mongo:4'
redis:
container_name: myapp-redis
image: 'redis:4.0.11'
In the above docker-compose.yml
I have defined the specific container services my application is required. The very first service is myapp having container name myapp
and exposed the ports 4300
and 4301
which will build the current directory using Dockerfile
The links
property in myapp
service will be used to connect with these two (mongo
and redis
) services within the app.
The other two services are mongo
named as myapp-mongo
and redis named as myapp-redis
. These two services run an image mentioned in image
property with their specific version.
# Install node v10
FROM node:10
# Set the workdir /var/www/myapp
WORKDIR /var/www/myapp
# Copy the package.json to workdir
COPY package.json ./
# Run npm install - install the npm dependencies
RUN npm install
# Copy application source
COPY . .
# Copy .env.docker to workdir/.env - use the docker env
COPY .env.docker ./.env
# Expose application ports - (4300 - for API and 4301 - for front end)
EXPOSE 4300 4301
# Generate build
RUN npm run build
# Start the application
CMD ["npm", "run", "run:prod"]
In the above Dockerfile
the node:10
the image is taken on which our application will be running as myapp container service in docker-compose.yml
, set the working directory to /var/ww/myapp
docker will create the directory if not exists.
Copy the package.json
from main machine root (where Dockerfile
lives) to the myapp container’s working directory.
Run npm install
into myapp
container to install the npm dependencies.
Copy the .env.docker
file to the working directory and renamed it as .env
The .env.docker
the file contains connection information for mongo
and redis
containers.
Expose the ports 4300
and 4301
on which applications (API and Frontend) are running.
Run npm run build
to generate application builds.
Start the application with CMD
command.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file
(default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name
(default: directory name)
--verbose Show more output
--log-level LEVEL Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the
name specified in the client certificate
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
--compatibility If set, Compose will attempt to convert deploy
keys in v3 files to their non-Swarm equivalent
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
myapp.sh
To make things easy let’s setup and bash script to run myapp application.
#!/bin/bash
CLEAN="clean"
RUN="run"
STOP="stop"
if [ "$#" -eq 0 ] || [ $1 = "-h" ] || [ $1 = "--help" ]; then
echo "Usage: ./myapp [OPTIONS] COMMAND [arg...]"
echo " ./myapp [ -h | --help ]"
echo ""
echo "Options:"
echo " -h, --help Prints usage."
echo ""
echo "Commands:"
echo " $CLEAN - Stop and Remove imoney containers."
echo " $RUN - Build and Run imoney."
echo " $STOP - Stop imoney."
exit
fi
clean() {
stop_existing
remove_stopped_containers
remove_unused_volumes
}
run() {
echo "Cleaning..."
clean
echo "Running docker..."
docker-compose up --build
}
stop_existing() {
MYAPP="$(docker ps --all --quiet --filter=name=myapp)"
REDIS="$(docker ps --all --quiet --filter=name=myapp-redis)"
MONGO="$(docker ps --all --quiet --filter=name=myapp-mongo)"
if [ -n "$MYAPP" ]; then
docker stop $MYAPP
fi
if [ -n "$REDIS" ]; then
docker stop $REDIS
fi
if [ -n "$MONGO" ]; then
docker stop $MONGO
fi
}
remove_stopped_containers() {
CONTAINERS="$(docker ps -a -f status=exited -q)"
if [ ${#CONTAINERS} -gt 0 ]; then
echo "Removing all stopped containers."
docker rm $CONTAINERS
else
echo "There are no stopped containers to be removed."
fi
}
remove_unused_volumes() {
CONTAINERS="$(docker volume ls -qf dangling=true)"
if [ ${#CONTAINERS} -gt 0 ]; then
echo "Removing all unused volumes."
docker volume rm $CONTAINERS
else
echo "There are no unused volumes to be removed."
fi
}
if [ $1 = $CLEAN ]; then
echo "Cleaning..."
clean
exit
fi
if [ $1 = $RUN ]; then
run
exit
fi
if [ $1 = $STOP ]; then
stop_existing
exit
fi
myapp.sh
Usage:
./myapp [OPTIONS] COMMAND [arg...]
./myapp [ -h | --help ]
Options:
-h, --help print usage.
Commands:
clean - Stop and Remove all containers.
run - Build and Run myapp.
stop - Stop myapp.
It’s been almost two and a half year since I am using Docker in all of my projects and it really helps me develop and deploy applications faster.
Whenever a new developer on-board to any of my application all he had to do is install docker on his machine and Docker will take care of everything else.
No more version issues and no worries for dependencies.
Let me know how Docker helps you with your applications.
Google Develover Expert — WebTechnologies and Angular | Principal Architect at Naukri.com | Entrepreneur | TechEnthusiast | Speaker