> 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

![](/files/-MJV5Q4j-wTSTYAeQXtA)

* 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

![](/files/-MVgh4Z8tSzU_FAlokCK)

### 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

![](/files/-MJV9bWpMGFGht5DzvvM)

### 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

![](/files/-MJVBhHJlDUj9m5BCoBJ)

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

![](/files/-MJVDnRaLy8P9F7GOzzI)

### Start the instance

* Syntax

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

* Example

```
docker start 44ed
```

* Result

![](/files/-MJVOONzl3OaNolMrp8X)

### 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;

![](/files/-MJVRdXs1ohO5fi6L3_j)

## 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

![](/files/-MJVqKFJkMaueIYZm2SL)

* 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

![](/files/-MJVuBnHwntSEwxXBIm9)

## 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;

![](/files/-MJW6P_JOWi8Y5wt31tT)

* 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

![](/files/-MJWCpjA8jLjdC7C9Zys)

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

![](/files/-MJXM6HjAGX-Cz4aXgMU)

![](/files/-MJXMCa_S3LIHUb1a7t8)

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

## Volume

<figure><img src="/files/uFcOhRVnAOjGafq1Y60s" 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="/files/3IPxY340QC3eiZ8smBTH" 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/>" %}
