3.1 Create custom Docker Image

  • Custom Docker image can be created in two ways:
    1. Container
    2. Dockerfile

3.2 Container

Create image with ubuntu + apache + git + java

docker run -itd ubuntu
docker exec -it <containedID> /bin/bash

# inside docker
apt-get update
apt-get install apache2
which apache2
apt install git
apt-get install openjdk-11-jdk -y
exit

docker exec <containedID> which apache2
docker commit -m "ubuntu+apache+git+java" -a "Rajesh Kumar" <containedID> containerName

3.3 Dockerfile

  • Dockerfile is used to create custom docker image
  • It’s a text document that contains all the instructions users provide to assemble an image.
  • Instructions specify what to do when building the image.
  • Can have –> runtime env, libraries, environment variables, and configuration files.

Developer --> Define Dockerfile --> Creates Docker Image

3.3.1 Build Image

Create Dockerfile file and write all the commands

# Dockerfile --> filename

# step 1: Base image
FROM alpine
# alpine is an OS, min docker image, based on Alpine Linux
# Its small, simple and secure

# step 2: Executes while build
# And Install a software
RUN apk add binutils

# step 2.5: Configure that software

# step 3: Executes when container is created
# Set default commands
CMD ['echo', 'Hello World... from my first docker image']

Build and run docker image from Dockerfile

docker build .

docker run 52c2f751ef19
# Hello World... from my first docker image

3.3.2 Install mongo

Create Dockerfile file and write all the commands

# step 1: Base image
FROM alpine

# step 2: Install a software
# Alpine doesn't know where to find mongo, So add these
# GEt here: http://dl-cdn.alpinelinux.org/alpine/
RUN echo 'https://dl-cdn.alpinelinux.org/alpine/v3.6/main' >> /etc/apk/repositories
RUN echo 'https://dl-cdn.alpinelinux.org/alpine/v3.6/community' >> /etc/apk/repositories
RUN apk add mongodb=3.4.4-r0

# step 2.5: Configure that software
VOLUME ["/data/db"]
WORKDIR /data
EXPOSE 27017

# step 3: Set default commands
CMD ["mongod"]

Build docker image from Dockerfile

# No image name
docker build .

# With image name and tag
docker build -t mymongo .

docker run mymongo 

# Get mongo shell --> In new terminal
docker exec -it 3c4c643b3ec0 sh
mongo
show dbs

3.4 Concept of caching in docker

3.5 Node project for docker

Install node and initialize node

mkdir mynode
cd mynode

npm init -y
# This will create package.json
# package.json
{
  "name": "mynode",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

Update package.json

# package.json
{
  "name": "mynode",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.1"
  }
}

Create index.js and RUN: npm start –> visit localhost:8001

const express = require('express');
const app = express();

app.get("/", (req, res) => {
    res.send("<h1> Home Page</h1>");
})

app.listen(8001, () =>{
    console.log("App is running at 8001")
})

Create Dockerfile

FROM node:alpine

WORKDIR /usr/nodeapp

# COPY from my curr dir to docker WORKDIR
COPY ./ ./

RUN npm install

# npm start
CMD ["npm", "start"]

Build and Run –> visit localhost:8002

docker build -t nodeapp .

# Docker port is not linked to my-external port
docker run nodeapp

# docker run -p my-port:docker-port nodeapp
docker run -p 8002:8001 nodeapp

3.6 Dynamic linking local and docker folder

Previously if we make any changes in project dir/files, each time have to build and start the image

After linking the project dir as docker volume, rebuild is not required

docker run -it -v <local_dir>:<docker_dir> <Image> bash
docker run -it -v $(pwd):/root/app amritkr6/python-3.6.15:v1 bash

3.7 Flask Python App

Create flask app

# app.py

import os
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return f'Hello Flask'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Create Dockerfile

# DockerFile

FROM amritkr6/python-3.6.15:v1

WORKDIR /app

# Copy the requirements file and install dependencies
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code
COPY app.py app.py

# Expose the port the app runs on
EXPOSE 5000

# Command to run the application
CMD ["python", "app.py"]

Create requirements.txt file

# requirements.txt

Flask

Build and Run –> visit localhost:5000

docker build -t flask-app .
docker run -p 5000:5000 flask-app

Nginx

  • Create small HTML page
    • index.html, xyz.css
# Dockerfile
FROM nginx

# It copies all the files from curr-dir to nginx-dir
copy . /usr/share/nginx/html
  • Build and run
docker build -t myweb .

docker run -p 8080:80 myweb

# visit localhost:8080/

Dynamic linking local and docker folder

  • Directly hosting from my local folder
    • Not for production
docker run -p 8080:80 -v $(pwd):/usr/share/nginx/html myweb

# Check --> no changes made in docker folder
docker run -p 8080:80

More

# Dockerfile

FROM python:3.7-alpine
# Base Image --> alpine: light version of py

MAINTAINER London App Developer Ltd
# Optional

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
# Copy req.txt from project to Docker image

RUN apk add --update --no-cache postgresql-client jpeg-dev
# apk --> package manage that comes with alpine
# add --> add package
# --update --> update registry before update
# --no-cache --> Don't store this files & packages(Coz make container small)
# jpeg-dev --> Req for `Pillow`

RUN apk add --update --no-cache --virtual .tmp-build-deps \
      gcc libc-dev linux-headers postgresql-dev musl-dev zlib zlib-dev
# install temp required dependencies that are needed to install req.txt
# musl-dev zlib zlib-dev --> for `Pillow`
# Other for --> `psycopg2`

RUN pip install -r /requirements.txt
# Take req.txt and install it

RUN apk del .tmp-build-deps
# Remove those temp files

RUN mkdir /app
# Make a empty dir

WORKDIR /app
# Switch it as default/currrent dir

COPY ./app /app
# Copy our project to docker image

RUN adduser -D user
# Create user to run-only(-D) the project

USER user
# Switch to user