> For the complete documentation index, see [llms.txt](https://petercheng7788.gitbook.io/developer-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://petercheng7788.gitbook.io/developer-note/devop/docker.md).

# Docker

## Introduction

* Provide light-weight virtual environment with suitable version for program to execute in order to run the program smoothly and prevent conflict due to version issue

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJV4ttt0Otd3UKBitzD%2F-MJV5Q4j-wTSTYAeQXtA%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8A%E5%8D%8811.54.36.png?alt=media\&token=0b46170e-d86f-4bf2-8962-837c82e17dc8)

* Registry: the link that used to get docker image ,which is similar with git repository
* Image: a template of docker for creating container
* Container: a light-weight virtual environment that run the instance of docker image

## Virtual Machine vs Docker

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MVgaFvhL5QfFoAGucIB%2F-MVgh4Z8tSzU_FAlokCK%2Fimage.png?alt=media\&token=2ed3deaf-bf29-4374-8256-79891a491537)

### Virtual Machine

* Initially, we need one physical server for one application, which is expensive and cannot make good use of all of the memory and CPU
* After virtualization, several virtual machines is isolated from host operation system which contains their own guest operation system and share CPU and memory from the computer
* Therefore, different operation system can be existed in a server to run multiple applications

### Docker

* Docker containers which creates a virtual environment can run at the same time by using the same host operation system
* Therefore, the boot up time will be shorter and becomes light-weight compared with virtual machine
* The image registry provides the portability, so that the image is easily to be reused across different machines

## General Flow

### Summary

1. Pull the Image from registry
2. Create new instance of container based on docker image
3. Start the instance&#x20;
4. Execute the instance

### Pull the image

* Syntax

```
docker image pull (image-name):(version)
```

* Example

```
docker image pull mysql:8.0
docker image pull mysql
docker image pull ubuntu
```

If the version is not defined, the default version will be latest

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJV8XPc4XJ5URnr3dIr%2F-MJV9bWpMGFGht5DzvvM%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%8812.13.53.png?alt=media\&token=6bb0af0a-4d39-4b5a-9e01-c599356d59e7)

### Create New Instance

* Syntax
* -d means run in background
* -p defines the port run in local
* -v defines the location of volume to backup the data in local,  so that the data can be shared between different containers

```
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
```

* Example

```
docker run  -d -v /Users/petercheng/Desktop/Jenkins:/var/jenkins_home 
-p 8080:8080 -p 50000:50000 --name my_jenkins_container jenkins/jenkins:lts 

 docker run --name=mysql_container -d -v 
 /Users/petercheng/Desktop/mysql:/var/lib/mysql 
 -p 3316:3306 --env MYSQL_ROOT_PASSWORD=1234  mysql/mysql-server
```

&#x20;If the name is not defined, the name will be generated randomly

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJV9pJdoCaTXhQjUFek%2F-MJVBhHJlDUj9m5BCoBJ%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%8812.22.51.png?alt=media\&token=c25d15a2-7864-4589-ada3-cd7347b77763)

From the list, we can see that there is 2 instances that we created with their name and container id

### Remove the instance

* Syntax

```
docker rm (container id)
```

* Example

```
docker rm 0504
```

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVC8m4nnpJX-pPVXGP%2F-MJVDnRaLy8P9F7GOzzI%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%8812.32.12.png?alt=media\&token=7b6ebc33-8ce9-4cc2-b405-fc2f9f932380)

### Start the instance

* Syntax

```
docker start (container id)/(container name)
```

* Example

```
docker start 44ed
```

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVIBOlneVNcbklz_5v%2F-MJVOONzl3OaNolMrp8X%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%881.18.39.png?alt=media\&token=19648247-073b-4de9-a1a7-146710a8e720)

### Stop the instance

* Syntax

```
docker stop (container id)/(container name)
```

* Example

```
docker stop 44ed
```

### Execute the instance

* Syntax

```
docker exec -it (container id)/(container name)
```

* Example&#x20;

```
dokcer exec -it test bash
```

* Result&#x20;

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVIBOlneVNcbklz_5v%2F-MJVRdXs1ohO5fi6L3_j%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%881.18.39.png?alt=media\&token=e116c956-22e3-4a68-a65e-7d68548da9cd)

## Customize Image

* Commit the container

```
docker commit (CONTAINER_ID)/(CONTAINER_NAME)
```

* Check whether new image is created or not and its image id

```
docker image ls
```

* Edit the name of new image

```
docker image tag <IMAGE_ID> <YOUR CUSTOM NAME>
```

## Push / Pull Image

* Register an account and create new repository on dockerHub

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVowOiRJODwVwgUf66%2F-MJVqKFJkMaueIYZm2SL%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%883.23.25.png?alt=media\&token=7ec87de2-1dc8-4c9b-9369-26f4c78e0f2a)

* Login&#x20;

```
docker login
```

### Push

* Change the name

```
docker tag <Your image> <account_name>/<repository_name>
```

* Example

```
docker tag custom_ubuntu headshootcheng/test
```

* Push to registry

```
docker push headshootcheng/test
```

### Pull

```
docker pull headshootcheng/test
```

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVowOiRJODwVwgUf66%2F-MJVuBnHwntSEwxXBIm9%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%883.42.01.png?alt=media\&token=d867a305-d3d0-409b-a423-e9ba9410a39c)

## Push image to GCP

* Login to gcp&#x20;

```
gcloud auth login
gcloud auth configure-docker
```

* Change the name of image and push google cloud container registry

```
docker tag ${IMAGE_NAME} asia.gcr.io/${YOUR PROJECT ID}/${IMAGE_NAME}

docker push asia.gcr.io/${YOUR PROJECT ID}/${IMAGE_NAME}
```

## Docker File

### Introduction

* Initially, we need to execute the container and then generate new image, which is inconvenient.
* Instead, we can write a script on docker file in order to automatize the process
* It is a material of making a template (docker image)&#x20;

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJVujSjxwsj6wtXV8fF%2F-MJW6P_JOWi8Y5wt31tT%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%884.39.26.png?alt=media\&token=987be9bd-05bf-4ec2-ba77-5f0f2933519d)

* FROM : from the original source of image
* RUN:  execute the command&#x20;
* COPY: copy file to specific directory
* WORKDIR: cd into specific directory
* CMD: execute the program on container, such as: node index.js

### Example

* Edit Dockerfile

```
// Dockerfile
FROM ubuntu
RUN touch hello.txt
CMD ["bash"]
```

* Create New Image by executing Dockerfile

```
docker image build -t custom_image
```

* Create + Start + Execute the container , and then see the result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJWAhXHZcz9wqIBERwM%2F-MJWCpjA8jLjdC7C9Zys%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%885.07.25.png?alt=media\&token=985577e9-b382-4e2f-b483-532b644416d6)

we can see that hello.txt is here

### Entry Point vs CMD

* `ENTRYPOINT` should be defined when using the container as an executable.
* `CMD` should be used as a way of defining default arguments for an `ENTRYPOINT` command or for executing an ad-hoc command in a container.
* `CMD` will be overridden when running the container with alternative arguments.
* ENTRYPOINT can be changed using the `--entrypoint` flag, but this should rarely be necessary for container images being used in the way they were intended.

```docker
ENTRYPOINT ["/usr/bin/my-app"]
CMD ["help"]
```

```
# Executes /usr/bin/my-app help
$ docker run my-image:latest

# Executes /usr/bin/my-app version
$ docker run my-image:latest version

# Executes bash -c "ls /"
$ docker run --entrypoint bash my-image:latest -c "ls /"
```

| <p><br></p>                       | No ENTRYPOINT                | ENTRYPOINT exec\_entry p1\_entry | ENTRYPOINT \["exec\_entry", "p1\_entry"]           |
| --------------------------------- | ---------------------------- | -------------------------------- | -------------------------------------------------- |
| **No CMD**                        | error, not allowed           | /bin/sh -c exec\_entry p1\_entry | exec\_entry p1\_entry                              |
| **CMD \["exec\_cmd", "p1\_cmd"]** | exec\_cmd p1\_cmd            | /bin/sh -c exec\_entry p1\_entry | exec\_entry p1\_entry exec\_cmd p1\_cmd            |
| **CMD exec\_cmd p1\_cmd**         | /bin/sh -c exec\_cmd p1\_cmd | /bin/sh -c exec\_entry p1\_entry | exec\_entry p1\_entry /bin/sh -c exec\_cmd p1\_cmd |

## Docker Compose

### Introduction

* In a big scale, we may need to execute several containers, it is time-wasting to create and start them one by one.&#x20;
* By writing a script docker-compose.yml, the process can be executed automatically

### Example

* Writing docker-compose.yml

```yaml
version: "3"
services:
  sql:
    restart: always
    image: "headshootcheng/keungsql"
    volumes:
      - "./config.conf:/etc/my.cnf"
    environment:
      MYSQL_ROOT_PASSWORD: "1234"
    ports:
      - "3316:3306"
    container_name: keungsql
  ubuntu:
    image: "headshootcheng/test"
    tty: true
    container_name: keungUbuntu
```

* Execute the command

```bash
# Start
docker-compose up (-d)

# Stop
docker compose stop

# Trace log
docker compose logs <name>
```

* Result

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJXIaPJj15SBvLiQYH8%2F-MJXM6HjAGX-Cz4aXgMU%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%8810.27.39.png?alt=media\&token=2ad60b2b-b4e2-451c-aeac-8a4207c4499f)

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MJXIaPJj15SBvLiQYH8%2F-MJXMCa_S3LIHUb1a7t8%2F%E8%9E%A2%E5%B9%95%E6%88%AA%E5%9C%96%202020-10-13%20%E4%B8%8B%E5%8D%8810.28.25.png?alt=media\&token=6409aaf3-612f-4612-8e8b-d8ea956e6aaa)

* 2 instances of container with 2 different images are created and started

## Volume

<figure><img src="https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFW3x2aqEO8GF2kr3VU%2Fuploads%2FSOpbLB23TszTnwNMOdYd%2Fimage.png?alt=media&amp;token=01540c58-31cc-4c49-a5df-f79c9840c7f1" alt=""><figcaption></figcaption></figure>

* When creating volume, the folder will be created on the machine to host the data

```bash
docker volume create --name db-data
docker volume ls
```

* Attach the volume to connect with path declared on the containerized environment

```bash
docker run -v db-data:/db/data -it ubuntu ls -la /db/data
docker run -v db-data:/db/data -it ubuntu touch /db/data/file
docker run -v db-data:/db/data -it ubuntu ls -la /db/data
```

* The same volume is shared among the above commands, so the result&#x20;

<figure><img src="https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFW3x2aqEO8GF2kr3VU%2Fuploads%2Fh3np4mshyaSBFB1jXQJe%2Fimage.png?alt=media&amp;token=54337ab9-2393-4c3d-996d-8df969ceb4b2" alt=""><figcaption></figcaption></figure>

## Debug

* Create a docker file with meaningless entry point, so that we can execute the container to debug

```docker
# ...
ENTRYPOINT ["tail", "-f", "/dev/null"]
```

## Reference

{% embed url="<https://ithelp.ithome.com.tw/users/20103456/ironman/1320>" %}

{% embed url="<https://training.play-with-docker.com/>" %}

{% embed url="<https://yeasy.gitbook.io/docker_practice/>" %}
