2003: Google Created its internal cluster management system Borg
2004: Development Process Containers, which eventually became cgroups
2008: cgroups got absorbed in Linux Kernel in 2008, which led to development of LXC
2013: Docker was built on top of LXC
2015: Open Container Initiative (OCI) was created by Docker, CoreOS and others to standardize containers. Docker donated its container runtime runc to the OCI. Kubernetes was born.
2017 Onwards: Kubernetes emerged as a victor in Container Orchestrator Wars™. Seeds of alternative ecosystem were sewn with development of alternative tools like CRI-O, and Podman. Evolution is still ongoing.
docker run busybox echo "Hello Laravel Rajkot"
# List running containers
docker ps
# List all containers
docker ps -a
# Remove Exited Container
docker rm <container-name>
Run an interactive container
docker run -it --rm busybox sh
# List running processes
ps aux
# Exit from the container
exit
ps aux
Run a background container: nginx
# Visit the IP address of your docker host to see whether nginx is running
docker run -d -p 80:80 nginx:alpine
# Visit the IP address of your docker host to see nginx running
docker ps
# Check access logs
docker logs -f <nginx-container-name>
# Open Interactive Shell within a running container
docker exec -it <nginx-container-name> sh
# Navigate to the location where nginx default page is stored
cd /usr/share/nginx/html
Bind Mounts and Volumes
Docker Bind Mount: Mounting host directory/file into a container
Docker Volume: Create a virtual Volume managed by Docker that is mounted into a container
Volumes are prescribed as “preferred mechanism” for persistence by Docker due to various reasons mentioned here.
Bind Mounts are still simpler to manage for single host.
Override the nginx default page with bind mount
curl -o /tmp/index.html https://pastebin.com/raw/k8DyhGqf
docker run --rm -p 80:80 -v /tmp/index.html:/usr/share/nginx/html/index.html nginx:alpine
# Refresh the page
Docker Images and Dockerfile
Dockerfile - A template/script that generates Docker Image
Docker Image - Application environment packaged into files
Docker Container - Running application from Docker Image
–
docker images
Build our own image
Dockerfile
FROM nginx:alpine
ADD /tmp/index.html /usr/share/nginx/html/
Commands
curl -o Dockerfile https://pastebin.com/raw/WDznhx8n
docker build -t hello-nginx .
# See the image you built listed
docker images
docker run --rm -p 80:80 hello-nginx
Real-World Dockerfile
FROM node:10-alpine
EXPOSE 3000
ENV NODE_ENV production
RUN mkdir /app
WORKDIR /app
ADD package.json yarn.lock /app/
RUN yarn install --production --pure-lockfile
ADD . /app
CMD ["yarn", "docker:start"]
Image Building Best Practices
One process service per container.
Keep images stateless.
Build immutable images for each software release. Don’t mount code as volume.
Keep images as small in size as possible. Add only stuff that you need.
Minimize docker instructions/layers.
Utilize multi-stage builds to keep images simple wherever possible.
Utilize build cache as much as possible.
Create images to be polymorphic based on environment variables and arguments
Okay, it's nice to run a single process inside a container. But, my applications are more complex than that.
docker-compose
Nice little utility that lets you declare multiple docker commands withink a single yaml file.
If docker -> service, then docker-compose -> application
curl -o mysql-compose.yml https://pastebin.com/raw/BKudcBhb
docker-compose -f mysql-compose.yml up
# Observe the logs, let mysql server start and visit port 8080 on your IP address
docker-compose -f mysql-compose.yml down
Let’s run a Laravel Application inside Docker
git clone https://github.com/deltasquare4/laravel-hello-world
docker-compose up -d
docker stats
Advantages
No more “works on my machine”. Because of Immutable Code + Environment, literally the same thing runs in all the environments.
Dockerfile serves as documentation of your environment.
Going back to the older version never breaks. All the dependencies and environment are baked into the image.
Spinning up the application locally is very easy.
Forces good application design, and makes automation around deployment and scaling easier.
Offers isolation from other components from security persepctive.
Your applications are not tied to a cloud provider/VPS anymore. You can run it anywhere within minutes.
Drawbacks
Docker daemon runs as root. Can be a potential security risk.
All containers run as child processes of Docker daemon. Bringing down the daemon will bring down all the containers.
Persistent data is complicated. Servers cannot be treated as throwaway completely in case of stateful load.
Docker does much more than container management; is bloated as a result.