docker - alex-aleyan/linux_wiki GitHub Wiki

Sources:

Docker Image - just as the name states it's the an image of docker configurations, services. Each developer will clone the image from the remote repo onto their server.
Docker Container - a running instance of the Docker Image; Once the developer has cloned the Docker Image, he/she launches it which creates a running instance of the Docker Image known as Docker Container.
	Container provides a file system, environment configs/vars and application images all in one package.
	Port : Container has a Port number assigned to it which provides the means of talking to the application running inside the container.
		Container ports must be bound to different ports of the hosting OS in order to avoid conflicts.
	Virtual File System: container has its own abstraction of the Operating System (file system and enviroment) which is different from the host OS.

Docker vs VM:

Docker is a virtualization machine.
Docker virtualizes the Application Layer.
VM virtualizes the complete OS (KERNEL + Application Layer).

Linux based docker image may NOT be compatible with Windows hosts or older IOS due to differences in KERNEL (true for windows versions older than 10) Docker.
Prior installation check if 
	Docker can run natively (see if KERNEL is compatible with docker images; Docker does run natively on Windows 10!!!)
	Virtualization is Enabled.
Docker Toolbox is the solution in case the Docker is unable to run natively on your OS which abstracts away the KERNEL and makes it possible for the host to run different docker images.

Container port must be bound to different ports of the hosting OS.

Docker installation consists of:
	Docker Engine ???
	Docker CLI Client - user interface.
	Docker Compose ???
	Docker Machine ???
	Kitematic ???

Installation on Linux:
	Install Repos
	Install Docker
	(Optional) Install docker toolbox for systems with the KERNEL that doesn't support the docker.

<command examples begin>

## Installation:
docker install docker-ce=<VERSION>
# Create a container out of a specified image
docker run <IMAGE>
docker run hello-world

# To download and run an image (remember container is a running instance of the image):
docker run <IMAGE>:<VERSION>
# example:
docker run postgress:4.0
# specify the binding of the ports during the run command:
docker run -p<HOST OS PORT>:<CONTAINER PORT> <CONTAINER NAME>:<CONTAINER VERSION>
docker run -p6000:6379 redis -d
docker run -p6001:6379 redis:4.0

# list running containers using "process" or "image" option:
docker ps
#list all containers (running and NOT running):
docker ps -a
docker images

# to start a previously created container in detached mode:
docker run -d redis
# to stop a particular container:
docker stop <CONTAINER ID>
# to restart a particular container
docker start <CONTAINER ID>

# troubleshooting container:
docker ps
docker logs <CONTAINER ID>
docker logs <CONTAINER NAME>

# launch the docker container (kind of like chroot into a jail; ) 
docker exec -it <CONTAINER ID> /bin/bash
Exit

## Docker network:
# We gonna create two container "mongodb" and "mongo-express" and have them talk to each other via docker network:
docker network ls
docker network create mongo-network
docker run -p <HOST SIDE PORT>:<CONTAINER PORT> -d mongo --name <CONTAINER NAME> --net <NETWORK NAME>

docker run -d -p 27017:27017 -d -e MONGO_INITDB_ROOT_USERNAME=admin \
                                -e MONGO_INITDB_ROOT_PASSWORD=password \
                                --net mongo-network \
                                --name mongodb\
                                mongo

docker run -d -p 8081:8081 -e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \
                           -e ME_CONFIG_MONGODB_ADMINPASSWORD=password \
                           --net mongo-network \
                           --name mongo-express \
                           -e ME_CONFIG_MONGODB_SERVER=mongodb \
                           mongo-express
docker logs <CONTAINER ID>

## Docker Compose (example for the #docker network above):
# notice the --net mongo-network part is missing below since Docker Compose takes care of creating a common Network.
# save the file as *.yaml file (ex: mongo.yaml):
version:'3'
services:
    mongodb:
         image:
             mongo
         poarts:
             - 27017:27017
         environment:
             - MONGO_INITDB_ROOT_USERNAME=admin
             - MONGO_INITDB_ROOT_PASSWORD=password
    mongo-express::
         image:
             mongo-express
         poarts:
             - 8080:8080
         environment:
             - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
             - ME_CONFIG_MONGODB_ADMINPASSWORD=password
             - ME_CONFIG_MONGODB_SERVER=mongodb
# from command line:
# to start the containers use "docker-compose" command with "up" option:
docker-compose -f mongo.yaml up
docker ps
# to stop the containers and the created network:
docker-compose -f mongo.yaml down

## DOCKERFILE - blue print for creating docker images:

# new images are always based off of another image
FROM node # same as install node
# the envs better be stored in docker composed file so the image does not have to be rebuild everytime you need to modify the envs
ENV MONGO_DB_USERNAME=admin
    MONGO_DB_PWD=password
RUN mkdir -p /home/app # notice this will create a directory inside the container and not on the host OS
COPY . /home/app # since the copy command is not driven by RUN comman, copies file from host OS into the docker container's home/app.
CMD ["node","server.js"] # executes an entry point linux command (node is preinstalled since we are starting off of another image)

# creating an actual docker file
# create a file and name it Dockerfile
# add below code:
FROM node:13-alpine
ENV MONGO_DB_USERNAME=admin \
    MONGO_DB_PWD=password
RUN mkdir -p /home/app
COPY . /home/app # COPY <PATH WITHIN THE HOST OS> <PATH WITHIN THE CONTAINER>
CMD ["node","/home/app/server.js"]

# building the docker image:
# docker image has to be rebuild every time we modify the Dockerfile which seems obvious.
docker build -t my-app:1.0 <PATH TO DOCKER FILE>
# list available images:
docker images
# launch the container by running the image
docker run my-app:1.0 -d
docker logs <container ID>
docker exec -it <CONTAINER ID> /bin/bash # use /bin/sh if bash d.n. work

# removing docker image:
# must first remove the container
docker rm <container id>
# the docker image can now be removed
docker rmi <image id> 


## Private Docker Repository:

docker pull <REPO DOMAIN>.<IMAGE>
docker images
# tag the image with the repo link so the docker knows the repo to push it onto
# docker tag <LOCAL NAME /TAG/ALIAS> <REPO ADDRESS.IMAGE NAME>
docker tag my-app:1.0 amazonaws.com/my-app:1.0
#docker push <REPO ADDRESS>.<TAG>
docker push amazonaws.com/my-app:1.0
# modification took place, lets push new image:
# build a new image my-app:1.1:
docker build -t my-app:1.1 ./Dockerfile
docker images
# docker tag <LOCAL NAME /TAG/ALIAS> <REPO ADDRESS.IMAGE NAME>
docker tag my-app:1.1 amazonaws.com/my-app:1.1
#docker push <REPO ADDRESS>.<TAG>; but why not just use the tag since tag it attached to the <repo>.<tag>?
docker push amazonaws.com/my-app:1.1

## Deploying containerized app:

# open previously created, docker compose file named mongo.yaml : 
version:'3'
services:
    my-app:
         image: amazonaws.com/my-app:1.0
         ports:
             - 3000:3000
    mongodb:
         image:
             mongo
         ports:
             - 27017:27017
         environment:
             - MONGO_INITDB_ROOT_USERNAME=admin
             - MONGO_INITDB_ROOT_PASSWORD=password
    mongo-express:
         image:
             mongo-express
         ports:
             - 8080:8080
         environment:
             - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
             - ME_CONFIG_MONGODB_ADMINPASSWORD=password
             - ME_CONFIG_MONGODB_SERVER=mongodb
# launch container using the just created compose file:
docker-compose -f .yaml up

## Docker Volumes:




# 3 types of docker volumes:
# host volume:
docker run -v <HOST DIRECTORY/VOLUME> <CONTAINER DIRECTORY>
# anonymous volumes
# for each container, a directory is generated that gets mounted at /var/lib/docker/volumes/
docker run -v <HOST VOLUME/DIRECTORY>
docker run -v /var/lib/mysql/data # will actually reside in /var/lib/docker/volumes/<random-hash>/_data
# named volumes (the best): 
# an improvement of anonymous volumes
# once created, you can reference the volume by name and not the directory path:
docker run -v name:<CONTAINER DIRECTORY>

# In docker compose: 
version:'3'
volumes: # this allows the volumes to be shared between the containers
    db-data
services:
    mongodb:
         image:
             mongo
         poarts:
             - 27017:27017
         volumes:
             - db-data:/var/lib/mysql/data # notice it's a named volume
         environment:
             - MONGO_INITDB_ROOT_USERNAME=admin
             - MONGO_INITDB_ROOT_PASSWORD=password
    mongo-express::
         image:
             mongo-express
         poarts:
             - 8080:8080
         volumes:
             - db-data:/var/lib/mysql/data # notice it's a named volume
         environment:
             - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
             - ME_CONFIG_MONGODB_ADMINPASSWORD=password
             - ME_CONFIG_MONGODB_SERVER=mongodb

## docker volumes demo:
# docker-compose.yaml:
version:'3'
services:
    mongodb:
         image:
             mongo
         ports:
             - 27017:27017
         environment:
             - MONGO_INITDB_ROOT_USERNAME=admin
             - MONGO_INITDB_ROOT_PASSWORD=password
    mongo-express:
         image:
             mongo-express
         ports:
             - 8080:8080
         environment:
             - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
             - ME_CONFIG_MONGODB_ADMINPASSWORD=password
             - ME_CONFIG_MONGODB_SERVER=mongodb

# launch the mongodb and mongo-express containers by executing the docker compose:
docker-compose -f docker-compose.yaml

# add volumes to your docker compose file:
version:'3'
services:
    mongodb:
         image:
             mongo
         ports:
             - 27017:27017
         environment:
             - MONGO_INITDB_ROOT_USERNAME=admin
             - MONGO_INITDB_ROOT_PASSWORD=password
         volumes:
             - mongo-data:/data/db #<volume>:<container dir>
    mongo-express:
         image:
             mongo-express
         ports:
             - 8080:8080
         environment:
             - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
             - ME_CONFIG_MONGODB_ADMINPASSWORD=password
             - ME_CONFIG_MONGODB_SERVER=mongodb
volumes:
    mongo-data:
        driver:
            local

# restart the containers:
docker-compose -f docker-compose.yaml

# docker volume locations:
Windwos: c:\PrograData\docker\volumes
Linux/IOS: /var/lib/docker/volumes


<command examples end>
⚠️ **GitHub.com Fallback** ⚠️