บันทึกการลองเล่น Docker
Tags: docker, devops
Published: 2020-10-20 04:38:21

## ท่าบ้านๆทั่วไปที่เจอกัน (Nestjs)
```dockerfile
FROM node:14-slim
WORKDIR /usr/src/app
COPY package*.json ./
# If you add a package-lock.json speed your build by switching to 'npm ci'.
RUN npm ci --only=production
RUN npm i -g @nestjs/cli
# Copy local code to the container image.
COPY . .
# Display directory structure
RUN ls -l
# Expose API port
EXPOSE 3000
# Run the web service on container startup.
CMD [ "npm", "start" ]
```

**[Dockerfiles] -> build -> [Docker Image] -> run -> [Container]**

## Build
```bash
docker build -t {image-tag} {path}
```

## Run 
```bash
docker run -p {out_port}:{in_port} -v {out_path}:{in_path} {img_tag}
#example 
docker run -p 8888:8888 -v pwd:/work docker-example
```

- **-p** คือการ map port จากข้างใน Container มาข้างนอก
- **-v** คือการ map work directory ข้างในกับข้างนอก เพื่อที่เวลาเราแก้ไขไฟล์ที่เครื่องของเรามันจะเซฟกลับเข้าไปที่ใน Container ด้วย

Options เพิ่มเติม
- **- entrypoint=** : กำหนด entrypoint เองแทนส่วนใน Dockerfiles
- **- e** : กำหนด environment variables ด้านใน container
- **- d** : สั่งรัน container แบบ detached หรือคือเป็น background process

### อธิบายเพิ่ม
โดยปกติ ports ที่ถูกเปิดไว้ภายใน container นั้นจะไม่สามารถเข้าใช้งานบน
Docker Host ซึ่งการที่จะเข้าใช้งานได้นั้นต้องทำ publish port ที่ต้องการก่อน ตั้งแต่ขั้นตอนการสร้าง container ขึ้นมา

สรุปคำสั่งใน docker file
- **FROM** เลือก base image (pull มาาจาก dockerhub)

- **RUN** execute command

- **CMD** execute command แต่มีได้แค่ครั้งบเดียวใน file ถ้ามีมากกว่าหนึ่งจะใช้อันสุดท้าย หรือใช้เป็น default parameter ให้ ENTRYPOINT

- **LABEL** ใส่ metadata ให้ image

- **EXPOSE** กำหนดให้ container รอรับ request ตาม port ที่กำหนด ใช้คู่กับ  -p ตอนใช้ docker run

- **ENV** กำหนดตัวแปร environment ให้ตอนทำ image และ container

- **ADD** copy file เข้า image

- **COPY** copy file เข้า imageต่างกับ ADD ตรงที่ไฟล์ต้นฉบับได้เฉพาะ local เป็น remote url ไม่ได้

- **ENTRYPOINT** คำสั่งที่จะให้ run หลังจากstart container

- **VOLUME** กำหนด mount point ให้ image

- **USER** กำนหด user ที่จะใช้ run คำสั่ง RUN CMD ENTRYPOINT

- **WORKDIR** กำหนด working directory  สำหรับ  RUN CMD ENTRYPOINT COPY ADD

- **ARG** กำหนดตัวแปรไว้สำหรับตอน BUILD

- **ONBUILD** ใช้สำหรับให้ run คำสั่งแต่ให้รอ trigger เพื่อทำงานต่อในกรณีที่ต้องรอให้ build ตัวอื่นก่อน

- **STOPSIGNAL** สั่งให้หยุดโดยใช้ system call signal

- **SHELL** เปลี่ยนไปใช้ shell ที่กำหนด

## คำสั่งที่ใช้บ่อย ๆ

- **docker rm** : ใช้ลบ container
- **docker rmi** : ใช้ลบ image / image tag
- **docker start** : start container ที่ถูกสร้างมาแล้วแต่ไม่ได้อยู่ในสถานะ running
- **docker stop** : ใช้หยุดการทำงานของ container ที่ running อยู่
- **docker ps** : ดู container ทั้งหมดที่ running อยู่
- **docker ps** -a** : ดู container ทั้งหมดที่เคยถูกสร้างขึ้นมา
- **docker exec -it ${CONTAINER_ID} bash** : ใช้เพื่อเข้าไปใน Container ->
- **docker rmi -f $(docker images -a -q)** delete all the images,
- **docker rm $(docker ps -a -q)** delete all the contanier
**reference**
- [คู่มือ Docker ฉบับผู้เริ่มต้น](https://medium.com/@noomerzx/%E0%B8%84%E0%B8%B9%E0%B9%88%E0%B8%A1%E0%B8%B7%E0%B8%AD-docker-%E0%B8%89%E0%B8%9A%E0%B8%B1%E0%B8%9A%E0%B8%9C%E0%B8%B9%E0%B9%89%E0%B9%80%E0%B8%A3%E0%B8%B4%E0%B9%88%E0%B8%A1%E0%B8%95%E0%B9%89%E0%B8%99-c1b9dc3b3645)

- [มาลองใช้ docker กันดีกว่า](https://medium.com/@somprasongd/%E0%B8%A1%E0%B8%B2%E0%B8%A5%E0%B8%AD%E0%B8%87%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99-docker-%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B8%94%E0%B8%B5%E0%B8%81%E0%B8%A7%E0%B9%88%E0%B8%B2-305fb178d22b)


## DockerCompose 

แก้ปัญหา build dockerfile หลาย ๆ file


### คำสั่งที่ดูจะคล้ายกัน

- **docker-compose up** to start or restart all the services defined in a docker-compose.yml

- **docker-compose run** command is for running “one-off” or “adhoc” tasks. It requires the service name you want to run and only starts containers for services that the running service depends on
- **docker-compose start** Starts existing containers for a service.

[Doc](https://docs.docker.com/compose/reference/up/)

https://www.jittagornp.me/blog/install-docker-compose-on-ubuntu-18.40/

## คำสั่งที่เรามักจะหลงกลไกการทำงานของมัน

- docker-compose up  ไม่ได้ rebuild images แต่ start 
- docker-compose up --build  rebuild and start
- docker-compose build rebuild เฉย ๆ

## เรื่องที่ผมเพิ่งเข้าใจ
> แบบเข้าใจง่าย ๆ ก่อน
- CMD  คือ run OS แล้วทำงานเลย
- entrypoint คือเหมือน shortterm คำสั่ง

## ว่ากันด้วยเรื่อง Shell and Exec Form 
> เกี่ยวกับ CMD and entrypoint 

![Screenshot_1](https://dev-to-uploads.s3.amazonaws.com/i/uuzeunkywq2sz7oj5ny4.png)
[shell and Exec คืออะไร?](https://docs.docker.com/engine/reference/builder/#run)

---
 

## เรื่องที่มักจะสับสน

**PORT** ใช้เพื่อ mapping host server and Docker container  
 > example 8080:80
 > 80 in the container to port 8080 on the Docker host

**EXPOSE** ใช้เฉพาะกำหนด port application running

### ที่มาของปัญหา

![image](https://dev-to-uploads.s3.amazonaws.com/i/jvmgq240j5qy3mjtermt.png)

- รูปแรกลงอะไรจะอยู่ใน OS ก้อนเดียว version จะชนกันยับๆ
- ใช้ VM  HYPERVISOR ตัวนี้จะเป็นตัวจำลองการทำให้ให้ VM provide hardware เข้าไปใน Guest OS ได้เพื่อเข้าไปลง OS ให้มันทำให้ **เปลืองทรัพยากร เสียเสียเวลา** แล้วถึงจะลง application ที่เราต้องการได้

- container docker agent จะจัดการ users space แบ่งแต่ละกล่องออกมาอย่างชัดเจน เช่น permission โดยที่ไม่กระทบ root ตัวจริง
การ mapping network

![image](https://dev-to-uploads.s3.amazonaws.com/i/q9icawpgpnx03s3vslye.png)
 
![image](https://dev-to-uploads.s3.amazonaws.com/i/fsc8wta99otjrwu36c82.png)