# Docker Images and Containers
###### tags: `Docker`

[TOC]
# Images
## What are images?
Templates/ Blueprints for containers. These will contain the code and required tools/runtimes needed for container, which will be the running instance of the image.
We can use an image to create multiple containers, different machines and servers.
## Where to get Image File?
### Finding/Creating Image
> Existing Image/Pre-Built Image
> We can find some in [Docker Hub](https://hub.docker.com/) or community groups.
[color=lightblue]
### Create our own custom image
Usually you start with **FROM** instruction, followed by stating **WORKDIR**(Work Directory) and finally **COPY** the files.
> [color=orange]
**DockerFile Step by Step:**
> [color=orange]
```==
//Command used to tell Docker to build a new custom image
//Last dot specifies the location of the image
docker build .
```
> [color=orange]
>In this case, our terminal it is already in the project path, that is why we use . to state root of that folder.
**Note:**
Images are **READ-ONLY**, if you want to change something in file, you have to rebuild image, unless you know how to update it.
>**Error**:
**failed to solve with frontend dockerfile.v0: failed to create LLB definition: the Dockerfile cannot be empty** means you did not save your dockerfile changes. Save it and run the command again. [color=red]
## Image Layers
### What are image layers?
Each instruction in an image creates a cachable layer, which helps with image re-building and sharing, so when rebuilding the same image it takes smaller time.
Each layer (instruction) is cached once, if we did not change anything, the next time we are building, then it all grabs from cache. However, for example, I changed some code, then all instructions after .COPY will be redone instead of using CACHE (as we cannot promise it will not affect the actions afterwards).

### **SUGGESTION for DOCKERFILE:**
That is why we suggest to run **COPY package.json /app** && **RUN npm install** before **.COPY**, because they usually do not change and it will save up time.

## Run Image (docker run imgName)
Find an image in **Docker Hub**, in this case node as example.
>[color=pink]
```=
//Create contained based of image found in docker hub
//(Ex: docker run node)
docker run imageName
//Check container creation by seeing all processes of all containers.
//ps > process | -a > all
docker ps -a
```
>[color=pink]
## Run Interactive Image (docker run -it imgName)
```==
// Expose an interative session from inside the container to our machine
// -it > interactive
docker run -it node
```
>Interactive Node Terminal
>[color=lightblue]
This command will just open an interactive node terminal, where we can use basic node commands. It is running in container, not in our machine.
>Node Version Difference in container and machine
>[color=lightblue]
**PS:** Quit Container by using **CTRL + C** twice.
## Sharing images
We usually share images, because **everyone who has an image can create containers based on the same image**.
### Sharing way 1: Share Dockerfile
Give dockerfile and project file. We simply **run docker build .**.
### Sharing way 2: Share a Built Image
Download an image and **run a container**.
## Pushing images to DockerHub
### Docker Hub
It is a free usage storage, can be private or public or official images.
1. First Create a Docker Hub Account
2. Sign In
3. Click Repositories on main page
4. Create Repository
5. Input image name, description and whether it is public or not. **Note:** We only have 1 private per account, and public is used, remember to avoid any relevant/private data inside.
6. Create Project
7. Log in in Terminal using **docker login**
8. Run in Terminal **docker push hubAccount/imgName** (Ex: docker push hubAccount/centos7-java8)
9. You will be done with pushing your image!
10. To pull the image use **docker pull hubAccount/imgName**




### Private Registry
Only
# Containers
## What are containers?
A standardized unit of software. This package will contain code and dependencies to run that same code.
https://www.docker.com/resources/what-container
## Why Containers?
1. Different Development and Production Environment.
We can assure the same version used. Ex: Same node.js version.
1. Different Development Environment within Team/Company.
1. Clashing Tools/Version between different projects. We do not wish to install/ uninstall tools when changing projects. Ex: Different version of Java in different projects.
# Managing Images & Containers
## How to check what commands docker has?
```==
docker --help
```
## How to check which containers are running?
```==
docker ps
```
## How to check all containers?
```==
docker ps -a
```
## How to check available config options for docker ps?
```==
docker ps --help
```
> [color=purple]
## Restart & Stop Containers
### How to Restart Containers? (Detached Mode)
>**docker run imgName** runs a new container always, so sometimes when we need to just restart a stopped container by using **docker start containerName** [color=green]
```==
//EX: docker start gallant_blackburn
//Use docker ps -a to check containerNames
docker start containerName
```
> [color=green]
>
>**PS:**
But **docker start** is running in the background, which means that container is running in **DETACHED MODE** (default mode).
### How to Restart Containers? (Attached Mode)
**Way 1:**
```==
//docker start -a gallant_blackburn
// a for attach
docker start -a containerName
```
**Way 2:**
>First, restart the container as detached one. After that, set it up as attached.[color=darkblue]
```==
//docker attach gallant_blackburn
docker attach containerName
```
>[color=darkblue]
### What are Attached and Detached Containers?
Attached Containers mean that we are always listening to the output. For example: console.log
### How to run new Container in detached mode?
Normally the default is **Attached Mode**. The **detached way** would be by using the below command:
```===
//By adding -d we are stating we want the detached mode
docker run -p localPort:exposePort -d imgName
```
If you regret and want to check logs, we can use the next command:
```===
//docker logs dreamy_franklin
docker logs containerName
```

If you want to re attach, use the next command:
```===
//docker logs -f dreamy_franklin
//-f for follow
docker logs -f containerName
```

## Enter Interactive mode
```===
// i = interactive, t = terminal
docker run -it imgName
```
### Restart interactive mode
```===
//docker start -a -i heuristic_jang
docker start -a -i containerName
```
## Deleting Images and Containers
### Delete Specific Containers
We can remove one or more containers by separating them with space.
```===
//docker rm vibrant_mendeleev strange_visvesvaraya
//rm = remove
docker rm containerName containerName
```
### Remove Stopped Containers
docker run -p 3000:80 -d --rm imgId
### Delete Specific Images
First we use **docker images** to check which images are still present. We **can remove only images that are not being used by containers no matter whether this container is running or not**.
```===
//docker rmi 6e72986b1b6e
//rmi = remove image
docker rmi imgId
```
When deleting it will show the images layers.

### Delete unused images all at once
```===
docker image prune
```
## Inspect Image
```===
docker image inspect imgId
```
## Make changes to a running container
Copy files into a running a running container or out of a running container.
**Copy into running container*:*
```=
//docker cp dummy/. wizardly_turing:/test
docker cp folder/. containerName:/locationInContainer
```
**Copy from container to local*:*
```=
//docker cp wizardly_turing:/test dummy
docker cp containerName:/locationInContainer file
```
# Naming Methods
## How to name containers?
```=
//docker run -p 3000:80 --name nodeapp 26ccd6d93835
docker run -p localPort:ExposePort --name naming imgId
```

## How to name images?
Images' naming consist on **name:tag**
```=
//docker build -t nodeversion:14 .
// -t = tag
docker build -t repositoryName:tag .
```

After naming the images, we can just run container using that name:tag image.
```=
//docker run -p 80:3000 --name nodeversiontest nodeversion:14
docker run -p localPort:exposePort --name containerName imgName:imgTag
```


## How to rename images
Rename an image by creating a new image with that new name.
```=
//docker tag nodetest:14 nodenew:14
docker tag oldImageName:oldTag newName:newTag
docker tag oldImageName:oldTag newName
```

docker run -p 3000:80 -d --name feedbackapp --rm nodetest:14
Run docker in localport 3000 to exposeport 80 in detached mode and name it feedbackapp and remove it when stopped, all using image nodetest:14