#Review#Docker#BeginnerDocker#VirtualMachine

What is docker 🚢

Docker is a platform for building, running and shipping applications. If it works from development then in production it definitely work .

Why the heck can something run in development but not in production ?

  • ✅ One or more files missing when going in production
  • ✅ Software version mismatch
  • ✅ Different configuration settings

With Docker We can package up our application with everything it needs and run it anywhere, with any machine that has docker.

  • ✅ All your package running in one plage
    • ✅ Django 4
    • ✅ Mysql 8
    • ✅ Vue js

How does it work

#Container Docker Provides a container where your application runs from and when you give it to somebody, they will not even spend any time installing dependencies or shit like that. he will just run one command and everything installs like by magic. When we don’t need an application anymore, we can remove it with all it’s dependencies in one go

Docker Is really good at helping us

  • 💡 Build
  • 🔥 run
  • [p] ship

virtual Machine Vs Container

#virtaulMachine#vm#Container

Virtual Machine vs Container

  • 💡 Virtaul Machine An abstraction of a machine (phisical hardware) Using a hypervisor such as virtaul box , vmware ,hyper-v you van create virtual machine
  • [d] Cons with VM
    • Each vm needs a full blown os
    • slow to start
    • Resource Intensive
  • 🔥 Container An isolated Environment for running an application
  • [u] Pros with Containers
    • ✅ Allow running multiple apps in isolation
    • ✅ Are lightweight
    • ✅ Use os of the host
    • ✅ start quickly
    • ✅ Need less hardware resources

Docker Architecture

Docker has A Client -> Server architecture. The Server, also called Docker Engine Sits in the back and is in charge of creating containers. Unlike VM containers do not contain a full os , instead all containers, share the os of the host, The kernel of the os.

Windows Docker Containers

From windows 10, Windows Support A custom built linux kernel therefore, can run Windows and Linux Containers

Linux Docker Containers

On a linux machine we can only run Linux Containers.

Mac

Mac os has it’s own kernel and has not have native support for containers, so on mac we use A light Linux VM to run docker.

INSTALL DOCKER.

#installation#setup#Docker#command Simply go on docker website and follow the instructions! After Install Docker, Check wheter it is installed or not.

docker version

Development work flow

Your application and Docker

To start of, we take an application, regardless of where it is build from and we Dockerize it. You simply add a docker file. The Docker FIle Is simply a text file that has instructions to help docker backages your applicaiton into an image.

Docker Image

This image contains everything our app needs to run.

  • [p] A cut-down Os
  • [p] A runtime Environement (Node)
  • [p] Application Files
  • [p] Third-Party Libraries
  • [p] Environment variables Once we have an Image, we tell docker to start a container, and that is how we run the app on our development server on our machine.
What about the image

Once we have the image we can push it to a docker registry such as docker hub which is just like pushing from git to github in it’s simple form. then we can move from The registry to the production.

  • 💡 Local Computer
  • [p] Docker Registry
  • 🔥 Test/Production

Let’s Imagine A scenario.

Let’s Say you have a simple js program to print hello world in the console. and you would like to go to production. here are the steps you will need to follow on the computes.

  • ✅ Start With an os
  • ✅ Install Node
  • ✅ Copy App files
  • ✅ Run node appname.js

Docker to the Rescue

Sample Program Process to use Docker.

In our dir/ We have a file app.js And this file contains a hello word program. I would like to ship it up to production.

step1 Create a docker config file

#configfile#Dockerfile Create a file in your working directory and call it Dockerfile and in the file write your configurations so that docker can create an image using the instructions of that file

Step2 Your Configuration file

#script In your config file, write your config.

#This images are published on docker hub,it's like inheriting in a programming language, kinda like getting the base components. There are multiple node images, they are build on multiple distro of linux. Alpine is a very small version of linux.
FROM node:alpine
#Copy our application or program files. the command bellow copy everything in a folder called app within an image
COPY . /app
#Set our current directory.
WORKDIR /app
# Use CMD commange to execute the program
CMD node /app.js
# And that is how we create configs.

Step 3 Building Our image

#command Now we want to tell docker to package up our application,

docker build -t hello-docker .
#command to build our image with hello-docker name of all files @ .

Node alpine and size

Because we used node from Linux alpine we ended up using 112 mb, This image contains , Alpine linux, Node, and our file.

List All Images on my computer

#command

docker image ls
# or also run
docker images
#Output looks somethings like this:
# Repository           Tag     Image id           Created      size
#hello-docker      latest    88759ee979f5   23 minutes ago   177MB
 
# Listing the id of running containers
docker image ls -q

Step 4 Running the Image

#command To run our application we simply run

docker run -it hello-docker

and our program will run perfectly. and we can publish that application anywhere we want ! amazing !

Linux Review

#linux#comman#ubuntu Docker is really built on top of linux, therefore, it’s highly recommended to have some basics in linux

Installing ubuntu

#command To install ubuntu, simply get it from the hub with the command bellow , which will pull the image from the hub to your computer.

docker pull ubuntu

#command

Shortcut

Instead of pull, you can also simply run :

docker run ubuntu

The command above will run the ubuntu file if it is on your local machine otherwise, it will download it and then run it.

#command#run

Running in the interactive mode

When we run the docker image of ubuntu with docker run ubuntu it started it but closed it after a while. To open a container you must use the interactive mode

docker run -it ubuntu

Docker Commands

#command

List Running Processes

list running proccesses

TO List running proccesses you simply type

docker ps
# ourput
# CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
  • [?] This will show the list of all running proccesses. Sometimes you want to see the list of all proccesses even stopped ones , That is when you use the flag -a
docker ps -a
# output
# CONTAINER ID     IMAGE     COMMAND     CREATED          STATUS     PORTS              NAMES
#  9b7acb43         ubuntu     "/bin/bash"     10 hours ago   Exited (0)   1m ago   musing_burnell

Running Ubuntu

Running ubuntu image

To run the ubuntu image you simply type docker run with the name of the image

docker run -it ubuntu
# output
# root@f19a5ceafe08:/#

Where

  • 💡 root : is the currently logged in use, by default is root who has the highest privilege
  • 💡 19a5.. : id is simply like the name of the machine
  • / : simply where we are at in the system
  • # : represent the highest privilege, in this case # is the root privilege

Running Containers vs Running images

When using docker you can run an image, which creates a new container, or simply run the previous container you had

Starting a new container with the run command

#run

docker run -it image_name
# docker run -it ubuntu
# whre -it : simply is the interactive mode
# Ubuntu : the image name

Starting a previously used container with the start command

#start

docker start -i container_id
# docker run -i 20845
# whre -i : simply is the interactive mode
# 20845 : the container name

Managing package manages

In this days, most os comes with package manages, such as

  • pip
  • npm
  • yarn ..
  • 💡 In ubuntu there is a package manager called apt : advanced package tool.

Install our first package

We want to install nano which is a basic text editor, then we simply type

root@f19a5ceafe08:/# apt install nano

The package database

In linux we have a package datatbase, it contains packages but none of them are installed. if you type apt list you will see a list of packages, you need to update the database so that new packages can be imported

# To update new packages > Simply type
apt update

Linux file system

In windows you have things like c:\windows , c:\users … In linux too you have directories too .

  • 🔥 / Is on the top of the hierarchy and it it the root
    • 💡 bin : Include binaries or programs
    • 💡 boot : all the files for booting are in here
    • 💡 dev: short for devices`(In linux everything is a file, so files that are need to acess devices are here)
    • 💡 etc: Short for editable text configurations
    • 💡 home: where users are installed
    • 💡 root: home directory of the root user
    • 💡 var: variables, where we have fiels that are updated freakwently
    • 💡 lib: keeps library files
    • 💡 proc: Include files that represent running processes

Environment Variables

just like we have variables in our programming languages, in linux you have environment variables that you can set to store config settings for our applications. so our application can read variables from the system

Commands to interact enviroment variables

  • 💡 printenv
  • This command is used to print all environment variables
    • 💡 Here you will get variables like
      • 💡 HOSTNAME
      • PWD
      • HOME
      • PATH

PATH Environment variable

The path variable is there to help your os identify where programs are located at, to find a program in your computer, the os won’t look through your entire disk, it will simply read the path and know where to look at.

it list the paths separating the different sources by :

printenv
# output
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# The above are directories that linux uses to find the location

#commans#printenv

#first Way
printenv PATH
#output
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 
#second way
echo $PATH
# you must prefix with a $ in front.

Set Environemnt variables

#commans#export This is the command used to set the environment varaible.

export DB_USER=danielerat
# This command is store in the current session of the terminal
 
echo $DB_USER
printenv DB_USER
#output
danielerat
  • [!] Note This variable is only available in the current session
  • 💡 To make it very consistent, then you have to add it to the .bashrc

Start, Stop, Restart a container

#commans#start#-i

Listing All the containers

To list the running Containers you simply use

# List all running containers
docker ps

Sometimes you want to list all the containers even the stopped ones, and to do that you simply run the commans:

# list all containers even closed ones
docker ps -a

Start A previously opened container

To start a contain you simply use it’s id with the start comman, first you must list to know the id of the container you want to start then use the start command with -i to interact with it.

docker start -i 2f2453
# where 2f2453 is the id of the container

#bashrc#reload

Reload the .bashrc file

Once you set a variable, alias or anything in the .bashrc file you need to restart it for the changes to take place, if you don’t want this you can simply restart it whith the source commans.

source .bashrc

Managing Processes

A process is an instence of a running program, To see all the running processes or program we can use the ps command

ps
#output
 PID   TTY          TIME    CMD
    1  pts/0    00:00:00   bash
#where pts: is the type of terminal, and the 0 simply means the first terminal window, if you open another one,...
#bash : the terminal we interract with. by default it is bash.

Killing a program or process.

#commans#kill To Kill a process you must know it’s id Let’s run a process in the background with the & Command

sleep 100 &
#our sleep command is running in the backgroun
 
ps
#output
 PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
  274 pts/0    00:00:00 sleep
 
#now let's say we want to kill it, simply type
kill 274

Managing users

Login with a different user in docker

docker exec -it -u danielerat 2fder bash

Step 1

Check the id of the running containers

  • 💡 docker ps

step2

Execute a bash session inside of the container

  • 💡
docker exec -it 2fder bash
# Execute another terminal window as root where:
# 2fder is the id of a container
#bash the sript we want to execute
#-it the interactive mode
#the commmand will be runned as root
 
docker exec -it -u danielerat 2fder bash
#execute the session with the new user danielerat logged in.
 

Managing user

you can create a group and add users to certain groups. Users in a group have same permissions.

Adding new user

To add a new user you simply type the groupadd command

groupadd developers
 
# The groups are saved in
# cat /etc/group
 

Adding user to group

# Adding user to a group:
# To add a user to a group you simply user the -G option:
usermod -G developers john
# Where developers is a group name

List group of a user

TO list the groups the user is apart of you simply use the command

groups danielerat
# Where danielerat is the group name

Permissions

Docker images, Building images

Having a solid understanding of building images is a must with docker You must have a solid understanding of

  • 🔥 Creating docker files
  • 🔥 versioning images
  • 🔥 sharing images
  • 🔥 saving and loading images
  • 🔥 Reducing image size
  • 🔥 Speeding up builds

Image Vs Containers

Image

An image contains all the files and application configurations needed to run an application, once we have an image we can start a container from it Contains:

  • ✅ A cut down os
  • ✅ Third-party libraries
  • ✅ Application files
  • ✅ Envrironment variables etc..

Container

A container it’s kinda like a virtual Machine, it provies an isolated environment for executing an application. so that we can start and stop a container, it’s just a process.

  • ✅ Provides An isolated envrironment to run your apps
  • ✅ Can be Stoppd and restarted as need
  • ✅ It’s just a proccess in it’s simple form

Starting a container from the same image

When you start a container from the same image, by default you don’t inherit anything from that image, therefore , everything you have in the first container is not gonna be included in your second container.

  • [!] A container gets all it’s file system from an image, but each container has it’s own right layer, what we write from one continer is invisible to the other container
  • [p] Of course there is a way you can share data from one container to another.

The Container universe

Each container is an isolated universe.

Dockerizing your applications.

  • 💡 Without Docker the steps of running a node project on a new machine looks like this:
    • ✅ Install Node
    • ✅ npm install (install all packages of the project)
    • ✅ npm start (run the server)
  • [u] This is very tidious, repetitive and time consuming. Now lets see how we can dockerize our app.

Docker File Instruction

The first step to dockerizing an application is to add a docker file to it. The Dockerfile contains instructions for building an image

Docker file Instructions

  • 🔥 FROM : This is used to specify the base image
  • 🔥 WORKDIR : Specify the working directory, so that all commands get runned within
  • 🔥 COPY : Copying files and directory
  • 🔥 ADD : Copying files and directory
  • 🔥 RUN : For running linux commands
  • 🔥 ENV : For setting environment variables
  • 🔥 EXPOSE : For telling docker that our container is starting on a given port
  • 🔥 USER : Specify who will run the application
  • 🔥 CMD : Specify the command that should be executed when we start a container
  • 🔥 ENTRYPOIN

Base image

Specify the base image, the base image can be an os or os+ a runtime environment if you are a c# developer, you want to start form a .net image, If you are from python developer, the from a python image, and js from a node image. you can find more from

Docker Configuration file:

Example steps of building your image.

Example of creating a docker image without application files.

# Since we are working with a node, then we can simply extend from node, (the alpine image which is very light and sufficient for our project.)
FROM node:19.0.1-alpine3.16
 
 

Building An image

Building an image for your application

To Build an image for your application, you simply need to go in the directory where there is your docker config file then you execute the buld command .

docker build -t vuejs-app .
# where the . is there to specify  the directory where the Dockerfile is at
You can list the images you have and the one you created will be apart
docker image ls
 
# REPOSITORY        TAG       IMAGE ID       CREATED        SIZE
# vuejs-app         latest    520823f8e31c   3 months ago   168MB

Starting the container with the created image

Running the image you created

Since you created your image from node:alpine , if you run the image, it will start a container with node environement

PS C:\Users\ilung> docker run -it vuejs-app
# Welcome to Node.js v19.0.1.
# Type ".help" for more information.
> console.log("i am in node console")
# i am in node console
 

Running Container specigying a command

You can run an image by specifying the command you want to run, IN the case above , it would help you run the bash script when running your container instead of the node one.

docker run -it vuejs-app sh
# alpine disto does not have bash, it comes with shell instead. that is why it is even small,

In this container, We also have node, cause it is combined with alpine

Copying application files and directories to your docker image

  • [!] For copying your application files you have two options to your hand: Copy and Add
  • 💡 With the copy command we can copy one or many files within the same directory or sub dir you are working on. there is not way to copy files from other locations, just files from where there is the Dockerfile

Copy files and directory

#copy#add#workdir

Example of creating a docker image without application files.

# Since we are working with a node, then we can simply extend from node, (the alpine image which is very light and sufficient for our project.)
FROM node:19.0.1-alpine3.16
 
# Copying our image files:
copy package.json /app
# the file package.json will be copied in the app folder in our image, if the file does not exist, then it will create it
 
copy package.json README.md /app/
#when copying multiple files, the destination has to be a dir, that is why we end the app/ with a slash
 
# yes you can copy files with spaces too
copy ['hello world.txt','README.md']  /app/
 
copy pack*.json /app/
# you can also use regular expression.
 
copy . /app/
#most of the time, we want to copy everything in our image, and boom there we go, we use .
  • 💡 as you can see, we are using an absolute path /app/ when specifying the destination folder, sometimes you want to set a relative path from a certain point. that is when you use the WORKDIR command.

Setting the working dir for relative path

We set the WORKDIR configuration to set our relative path .

FROM node:19.0.1-alpine3.16
WORKDIR /app
# Copying all your files to the relative path aka /app path, first dot means everything. second means here.
copy . .
 

Ignoring some files in docker

#dockerignore#gitignore#ignore Sometimes you just wan to ignore files, either it is for optimization or simply to reduce your build

  • 💡 Let’s say you have your node modules file, you simply don’t add them to your image,cause it will make those images big and hard to sharee.
  • [p] Instead you want to ignore the file and install the dependencies after the image is done building!

dockerignore file

Files you would wan to be ignored when executing your builds should be added in a file called .dockerignore, this way these files in dockerignore are not going to be added to our image when building.

[!success ] you can install the files if it’s node module let’s say you ignore a node_module file, you can easily get these files back after starting your image

Reinstalling node modules

Since you ignored a file such as node modules to make your bilds faster, you might want to reinstall it to your image otherwise your app simply won’t run! To execute commands we use the RUN Command. #run

Executing with the run commna

FROM node:19.0.1-alpine3.16
WORKDIR /app
COPY . .

RUN npm install
# the line above will install our node_modules and dependencies

Adding environment variables

#env#venv#variables let’s say you are wokring on your front end, and you would like to access the api for your backend over a specific url , then you might want to use environment variables #EVN

Executing with the run commna

FROM node:19.0.1-alpine3.16
WORKDIR /app
COPY . .
RUN npm install
ENV API_URL='HTTP://api.myapp.com/'
# Setting my environment variables.

Creating users and using them

  • 💡 Sometimes you want to create a user so that even if a hacker somehow gets access to our container, they won’t be having root user permissions, this not be bale to write on our app
    • 💡 For that we need to create a user and user that user inside of our app instead.
FROM node:19.0.1-alpine3.16
# Create a group and a user called danielerat
RUN addgroup danielerat && adduser -S -G danielerat danielerat
# select the user that will run this app, this way , nobody can have the right to edit or modify our files
USER danielerat
WORKDIR /app
COPY . .
RUN npm install
ENV API_URL='HTTP://api.myapp.com/'
EXPOSE 3000

Running our image

To run our image to a new container we simply will have to run docker run vuejs-app npm start

Command Instruction

#cmd#CMD#instructions Using the command instruction we can specify a default instruction to be executed. Meaning, instead of doing docker run veujs-app npm start to run the npm command we can use the CMD do help use be more clean

FROM node:19.0.1-alpine3.16
# Create a group and a user called danielerat
RUN addgroup danielerat && adduser -S -G danielerat danielerat
# select the user that will run this app, this way , nobody can have the right to edit or modify our files
USER danielerat
WORKDIR /app
COPY . .
RUN npm install
ENV API_URL='HTTP://api.myapp.com/'
EXPOSE 3000
# specify the default command  instruction
CMD npm start # Also called shell form
  #or
CMD ['npm','start']  #Also called Exec form
# The first run opens a new shell and run the command, the second with [] does not
#that is why it is always best prectice to use the second form
# with the second CMD [...] We execute without having the need to create a new process
	# or
ENTRYPONT["npm","start"]
# The cmd can be easily overidden when running the container ,
# docker run vuejs-app echo hello
# this will overidde our cmd command but to overidde the entrypoint you will need to use --entrypoint

Running our image

Now running our image will simply look something like this docker run vuejs-app

Docker layers

An image is simply a collection of several layers that are chained and executed one after another one, To view the build layers simply use: docker history vuejs-app

<missing>      2 hours ago   WORKDIR /app                                    0B        buildkit.dockerfile.v0
<missing>      12 days ago   /bin/sh -c #(nop)  CMD ["node"]                 0B
<missing>      12 days ago   /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<missing>      12 days ago   /bin/sh -c #(nop) COPY file:4d192565a7220e13…   388B
<missing>      12 days ago   /bin/sh -c apk add --no-cache --virtual .bui…   7.78MB
<missing>      12 days ago   /bin/sh -c #(nop)  ENV YARN_VERSION=1.22.19     0B
<missing>      12 days ago   /bin/sh -c addgroup -g 1000 node     && addu…   160MB
<missing>      12 days ago   /bin/sh -c #(nop)  ENV NODE_VERSION=18.14.2     0B
<missing>      3 weeks ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      3 weeks ago   /bin/sh -c #(nop) ADD file:40887ab7c06977737…   7.05MB`
 

Docker Cache

  • 💡 In the implementation bellow we make use of the docker optimization to allow it not to install npm every time
    • 🔥 To optimize your dockerfile you must
      • 💡 Order Instructions that don’t change often on the top
      • 💡 Order Instructions that does cange often on the bottom.
FROM node:lts-alpine3.17
 
WORKDIR /app
 
COPY package*.json .
 
RUN npm install
 
COPY . .
 
ENV API_URL='HTTP://api.myapp.com/'
 
EXPOSE 3000
 
CMD ["npm", "run","serve"]

Docker optimzation

Docker has an optimization built into it,

  • 💡 If a layer Did not change, Then docker is gonna use it’s cash

RUN vs CMD

Why would we even want to use CMD looks like run can perfectly do that job

  • 💡 RUN the run instruction is a built time instruction, it is executing at the time of building the image
  • 💡 CMD This is a run time instruction, it is executed when starting the container

Add files and directories

#add#copy#zip

Copy vs Add
  • 🔥 Copy does the same thing as add but it has two more additional commands
  • With add we can:
    • Add a file from a url
    • Add a zip file and add will uncompress it for you.

Add command

Add does what copy does with the ability of doing the above

ADD file.zip .
# in the case above add will unzip the file and simply make it accessible in your project dir
ADD https://yourUrl.json .
# Add will download that file and add it to your project file.

Rebuilding your image

#build#rebuild To rebuild your image you simply use the build command

docker build -t vuejs-app .
#command to build our image with hello-docker name of all files @ .

Running to see our copied files

  • 💡 To run our application we simply use the run command
docker run -it vuejs-app sh
# if you run the above without the sh it will run node instead
 

Docker run vs start

#start#run

  • 💡 The main difference between run and start docker is that
    • 🔥 run creates a new container from an image and starts it,
    • 🔥 start only starts an existing container that was previously created or stopped

Create a container and start it

To create and start a new container you simply use:

# start your image with the shell terminal
docker run -it vuejs-app sh

Start your previously created containers

To start the containers you previously had you simply run:

# start your created container
docker start -i 4111
#where 4111 is your container id

Revoming images

#none#prune#remove

  • 🔥 Sometimes when working in docker, you see those images with <none> in front of them, those are called, those are layers that are loose, when you rebuild your image docker create those layers and some point they lost relationship with your app

Removing those dangling images

To get ride of those zombies you simply use the prune command

 
docker images
# `<none>`      latest    42bae79e6170   3 days ago      177MB
#`<none>`      latest    42bae79e6170   3 days ago      177MB
 
# Removing specigic image
docker image rm 3234 1b2
# 3234 and 1b2 are the ids of the images you want to remove
 
# removing all images
docker image rm $(docker image ls -q)
# whre the the command in $( ) simply lists all the ids of your images
 
docker image prune
#this command will remove all those images
 
 
# You can also remove all stopped containers
docker ps -a
# the command above will list all containers include stopped ones
 
# removing all containers
docker image rm -f $(docker container ls -aq)
# whre the the command in $( ) simply lists all the ids of your containers , even stopped ones
 
docker container prune
#this will remove all stopped containers.

Removing docker images

  • 💡 All docker image management commads start with image docker image your_cmd To see the list of all commands you simply type
docker image
# output
 build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

Removing Particular image

#rm To remove a particular image you must either have a name or id

docker image rm vuejs-app
#or using id
docker image rm 32323
#for multiple files juse separate them with space
docker image rm vuejs-app hello-docker 3242

Docker Tags

#tag#image

  • 💡 Docker Tags are there to help use identify the version we are running in our environment, by default docker uses latest which is terrible, if you have a problem you won’t really know what version you are having issues with, therefore you should always add tags to your images

How to tag an image

  • 🔥 You have several ways of tagging your images,
    • 💡 You can tag them with
      • 💡 name: beaver,buster : Your team knows what this is
      • 💡 semantic versioning : 3.4.2 : common to team that does not release often
      • 💡 build numbers: 77 : team that build very often

Adding your tag

To ass your tag you simply add it after your image name

docker build -t vuejs-app:1
# where 1 is your build number
 
docker images
# REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
# vuejs-app         1    09d78de0adcb   29 minutes ago   307MB

Adding your tag after creating your image

Yes, you can add your tag after you have created your image, for that you simply use the tag command docker image tag vuejs-app:latest vuejs-app:1

Removing your tag

Sometimes you might want to remove your image tag for that you use the remove command docker image remove vuejs-app:1

Different version vs the lastest

  • 💡 We have an image with tag 1 which is supposed to mean first version of our applicaiton.
    • 💡 We made some changes and create another image with tag 2
    • 💡 Now we have 3 images, first with 1 tag, second with 2 and last with latest tag, which simply points to 1
  • 🔥 Listing our images
docker images
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
vuejs-app         1         09d78de0adcb   36 minutes ago   307MB
vuejs-app         latest    09d78de0adcb   36 minutes ago   307MB
  • 🔥 Creating a new image so simulate a new version (version2)
    • 💡 docker build -t vuejs-app:2 .
  • 🔥 Listing our images again
docker images
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
vuejs-app         2         654951fc90b7   7 minutes ago    307MB
vuejs-app         1         09d78de0adcb   44 minutes ago   307MB
vuejs-app         latest    09d78de0adcb   44 minutes ago   307MB
  • 💡 Now we have 3 versoin with the latest one simply pointing to the versoin 1

Change where latest is pointing to

As you can see the latest image is pointing to an older verison which is one, ther is a way you change where the image is pointing to with the tag command

docker image tag 654 vuejs-app:latest
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
vuejs-app         2         654951fc90b7   7 minutes ago    307MB
vuejs-app         1         09d78de0adcb   44 minutes ago   307MB
vuejs-app         latest    654951fc90b7   44 minutes ago   307MB
  • 💡 Now latest is pointing to the second version

Pushing our image to hub

  • 💡 You can push your docker app to hub in simple steps - ✅ Step0: Create a repo in our hub(danielerat/vue-app) - 🔥 step1: Rename your image wit the name of your repo form hub - 🔥 step2: Login to docker terminal - 🔥 step3: push your docker file #push#login#hub
#Steps to push to docker hub
- 💡 Step1
docker images
#output
#vuejs-app            2         654951fc90b7   33 minutes ago      307MB
#vuejs-app            latest    654951fc90b7   33 minutes ago      307MB
#vuejs-app            1         09d78de0adcb   About an hour ago   307MB
 
docker image tag vuejs-app:2 danielerat/vue-app:2
#output
#REPOSITORY           TAG       IMAGE ID       CREATED             SIZE
#danielerat/vue-app   2         654951fc90b7   43 minutes ago      307MB
#vuejs-app            2         654951fc90b7   43 minutes ago      307MB
#vuejs-app            latest    654951fc90b7   43 minutes ago      307MB
#vuejs-app            1         09d78de0adcb   About an hour ago   307MB
 
#login to your docker
docker login
 
#pushing your image
docker push danielerat/vue-app:2

Docker Saving vs loading

  • [p] Let’s say you want to save your docker image offline so that you can be able to reuse it on another machine. you can use docker hub but also there are command to do this offline
    • 💡 This is simple you simply use the save to save it offline and load to load it in our docker

Saving your docker file offline

You can save your docker file offline using the save command docker image save -o 'output_file_name image_name'

docker image save -o vue-app.tar vuejs-app:3

tar is simple the compressed version of the thing

Load your docker file to docker

You can also load your docker file to docker, you simply need to use the load command docker image load -i vue-app.tar

Working with containers

#containers

  • 💡 Now let’s have a look on how we can work with containers in details
    • 💡 Starting and Stopping containers
    • 💡 Publishing ports
    • 💡 vieweing logs
    • 💡 Executing commands in containers
    • 💡 removing containers
    • 💡 Persisting data using volumes
    • 💡 Sharing source code

Container Basics

Run a container

To run a given container from an image you use the run command.

# docker run image_name_or_id
docker run vuejs-app
# You can also use id instead of vuejs-app

#backgroud#detached

Running a container in the detached mode aka Background

To run an image in the background you use the -d flag

# docker run -d image_name_or_id
docker run -d vuejs-app

Running a container with your favorite name

Docker automatically runs an image and assings a name to it, you can run a container and give it your favorite name.

#docker run -d --name blue-sky image_name_or_id
docker run -d --name blue-sky vuejs-app

How do i see the running containers

To see the running containers you simply use the ps comman

docker ps
# see running containers.
 
#sometimes you want to see even close containers for that you use -a flag
docker ps -a

Viewing Logs

You have running containers, that is good, now what about them , they are in the background, you don’t know what’s happening , what is our server generates an error? What if something wrong happens, that is where we use the log command.

View Logs of docker

You can use the log command to view the logs of a running container in docker.

# docker logs process_id
docker logs 2083
 
# Folow the log in continuous mode, to see whatever is written on the log, in real time
docker logs -f 2083
 
# You have a log with a large  number of logs then you are glad to learn that you have a -n flag to help you
docker logs -n 34 2083
# this will output last 34 lines of codes.
 
# you want to output the timestamp ? yes you also have an option for that and it is -t
docker logs -n 4 -t 2083

Publishing ports

you have an application running on a ginve port in your docker container let’s say localhost@3000 and you would like to access the application in your host computer, you simply can publish the port and access it to your machine.

  • ✅ You need to publish a port to send trafic from your container to your host pc

Run container and publishing a part at the same time

You can run a container publishing a port at the same time. you just need the -p

docker run -d -p 8080:8080 --name dark-vador vuejs-app
# where the -p is used to specigy the port
	# 8080 : is your host port
	# 3000 is your docker port
	# --name : is to specigy your name tag

Execute a command in a running container

#exec#execute What if you want to execute a command in a running container how do you do that ? You use the the exec command. differently from the docker run command you start a new container and run a command , docker exec we execute a command inside of a running container.

Execute a command in a running container

If you want to run a command in a running container you can use the exec command.

docker exec veujs-app  ls
# you can run any command in here.
 
# Using the same approach you can run the shell
docker exec -it 208 sh

Stopping and running containers

#start#stop A container is such alight weight virtual machine, you can stop or start it! . for this you simply use the start or stop command.

Starting and stopping a container

You can start or stop a container using the approach bellow.

# docker stop container_name_or_id
docker stop balck_mamba

Docker start vs docker run

With docker run we create a new container and with docker start we start a stopped container

Removing a container

  • 🔥 Yup, you can remove a running container, yes it is possible and for that you use the rm command.

Removing a container

 
# docker container rm container_name_or_id
docker container rm black_mamba
 
# There is also a short version of that
docker rm black_mamba
 
# Removing a running container
#by default you can not remove a running container, you can either stop it or simply use the force command.
docker rm -f c1

Deleting all the stoppen

To delete all the running containers we use the prune command.

docker container prune

Container file system

#volumes Each container has it own file system that is invisible to other containers. If you have data that you would like not to delete, then you should not store them in a container, That is what volumes

Persisting data using volumes

#volume Volumes are storages outside of containers, It can be on the host or somewhere in the cloud. For that we use the volume command.

  • 💡 With the Docker volume Command we ca
    • 💡 create: create a volume
    • 💡 inspect: Display detailed di
    • 💡 ls: list volumes
    • 💡 prune: Remove all unused local volumes
    • 💡 rm: remove one or more volumes

Creating a new volume

To create a new volume we use the create command.

docker volume create app-data

Inspecting a volume

To inspect a volume you use the inspect command

docker volume inspect app-data

Using our volume in our container

We use the -v flag to set our volum

docker run -d -p 8080:8080 -v app-data:/app/data vuejs-app
#where
# -v is there to specify the volume and where the volume should be saved aka the absolute path.
  • [p] The beauty of volumes is that, if you delete a container, the data from the volume would still remain.
    • 💡 We can share volumes between multiple containers

Copying files between the host and the container.

Sometimes we wan to copy files between the host and the container. lets say you have this huge log file you would lilke to analyse . and the best way of doing so is by bringing the file offline to your host computer.

  • 💡 Docker has a copy command.

You can copy from host to container and container to host

To copy you simply use the copy command.

#docker cp container:absolute_pash_of_file   destination
docker cp black_mamba:/app/data/memo.txt .
# where /app/data/memo.txt is the absolute path to my file
# . i the destination of my file , which is my root folder directory.
 
# You can also move the way back, host to container
docker cp  secretFile.txt black_mamba:/app/data/memo.txt

Sharing the resource code with a container.

  • [?] So, you have a vue application running at localhost:8080 in your container, mapped to your port 8080 on your host and you would like to modify your codes. there are many approached you can fix this issue with:
  • [!] You modify codes in your Host Computer and to your surprise nothing is working, if you are suprised you might want to revise the basics you piece of shit , you can fix the issue by rebuilding the immage and running a new container or also do something else:

Publishing Changes

This is just a way you can overcome the issue above,

  • 🔥 For production: Build a new Image tag it properly and publish it.
  • 🔥 For development :
    • [-] you don’t want to build a new image it is simply time consuming
    • [-] You don’t want to Copy file files too
  • 🔥 Mapping: you can create a mapping between host and container

Dock.canvas

To create the mapping we can simply use the -v flag, used to map a volume.

  • 🔥 You can map the host directory containing your project to the app directory inside of your container in development environemnt to avoid you create images all the time .
docker run --name danielerat -d -p 8080:8080 -v $(pwd):/app vuejs-app
# where -d : is the detached mode
# -p : maps the port from the docker to env to our host env
# --name danielerat: is simply the name of our container
# $(pwd): name of our working directory, the one we want to map in docker
# -v : for specifying the volume but instead of using a docker volume,we use our files from our project on the host as a volume.
  • 💡 TO share our source code with a container we use the -v to map the project directory to a directory in the container’s file system.

Running multi Container Apps

  • 🔥 We saw all those commans to understand how docker compose works under the hood. now time to use the real stuff.
  • 💡 In this sectoin we are going to cover
    • 🔥 Docker Compose
    • 🔥 Docker Networking
    • 🔥 Database Migrations
    • 🔥 Running Automated Test.

Docker Compose

  • 💡 Docker compose, a tool built on top of docker engine, It makes it easy to start apps with multiple containers.

JSON and YAML format

  • JSON : is a human readeable language for representing data
{
  "name": "Ilunga Gisa Daniel",
  "age": 23,
  "is_maried": false,
  "hobby": ["chess", "cartoon", "basket"],
  "language": {
    "python": "4years",
    "django": "5monhts",
    "vuejs": "2monts"
  }
}
  • Yaml : just used to represent data too but less clustered compared to json
    • 🔥 Quite often we use yml for configurations and js for exchanging data
---
name: Ilunga Gisa Daniel
age: 23
is_maried: false
hobby:
	-chess
	-cartoon
	-basket
language:
	python: 4years
	django: 5monhts
	vuejs: 2monts

Compose file

version: "3.8"
# setting the version
services:
#naming our front end application
  frontend:
    depends_on:
      - backend
#Specify the build location for the front end
    build: ./frontend
    ports:
      - 3000:3000
#map a port of the frontend
 
  backend:
 
    depends_on:
      - db
#specigy the build location for the backend
    build: ./backend
# Map port of the backend
    ports:
      - 3001:3001
    environment:
      DB_URL: mongodb://db/vidly
    command: ./docker-entrypoint.sh
#setting up the database and port
  db:
    image: mongo:4.0-xenial
    ports:
      - 27017:27017
# setting up the volume to persist data
    volumes:
      - vidly:/data/db
volumes:
  vidly:

building the docker images

To build the images of your app you simply run th ecommand bellow

docker-compose build
 
#if you don't want cache when building an image you use --no-cache flag
docker-compose biild --no-cache

Starting the application

  • 🔥 Do run an application you simply use the up command, if our image are ready docker will start running them inside containers otherwise it will build the images automatically.
docker-compose up

Viewing logs

To view logs we use the logs command to view logs accross all our apps

#view logs of all your apps
docker-compose logs
 
# View logs of a specific app
docker-compose logs c834 -f
# where -f is all about continous output

Deploying your Applicaiton

Installing docker machine

To install docker machine you must make sure to be on a linux or if you are using windows to simply use git bach

# The latest release of how to install docker machine can be found bellow
https://github.com/docker/machine/releases
# use thi scommand to install
if [[ ! -d "$HOME/bin" ]]; then mkdir -p "$HOME/bin"; fi && \
curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" && \
chmod +x "$HOME/bin/docker-machine.exe"

Checking your installation

docker-machine --version

Creating your driver to digital ocean

To provision a driver or a computer from digital ocean which is simply a computer where your container will be running from you can use the command bellow

docker-machine create --driver digitalocean \
--digitalocean-image ubuntu-20-04-x64 \
--digitalocean-access-token=$DO_KEY name;
# where \ are simply marking the ending of a line

Listing your created machine

docker-machine ls
#name   Active  Driver      State     url                    Docker
#flower2 -     digitalocean Running tcp://68.183.48.149:2376  v24.0.2
 

Connecting to our remove machine

To connect to our remove machine we did provision with docker machine is as simple as SSHING into it!

docker-machine ssh flower2
#flower2 is the name of our machine

Docker ReminderCommands

CommandDescritpion
docker pull package_name Command To get an image from the docker hub to your pc
docker psList of running containers
docker ps -aWe see the list of running containers and the stopped ones too
docker run -it package_nameThis is to run a package in the interactive mode
docker start -i container_idThis is to run a docker container of which you know the id

Tips and tricks

Connect to a postgres terminal inside of a running container

// Find your process
docker ps
 
// CONTAINER ID   IMAGE      COMMAND   ...
// 08a09ae2c604   postgres   "docker-entrypoint.s…"
 
// Run a bash session inside of the terminal
docker exec -it 08a09ae2c604 bash
 
/*
08a09ae2c604 : your image
-it : Interactive mode
bash : bash session
*/