# การใช้งาน Docker

# การแก้ไขปัญหา IP Docker ชนกับ IP ภายใน

ปัญหานี้เกิดจาก ip subnet ของ docker ซึ่งปกติ ip subnet ของ docker จะเป็น 172.17.0.0 ไปชนกับ ip subnet ภายในของมหาวิทยาลัย ซึ่งเราสามารถเปลี่ยน ip subnet ของ docker ได้โดยการใช้ docker daemon และมีขั้นตอนการติดตั้งดังต่อไปนี้

1\. หยุดการทำงานเซอร์วิสของ Docker

```
sudo service docker stop
```

2\. สร้างไฟล์ daemon.json ในโฟลเดอร์ /etc/docker

```
sudo nano /etc/docker/daemon.json
```

จากนั้นใส่ค่าของ supnet ลงไปดังต่อไปนี้

```
{
  "default-address-pools" : [
    {
      "base" : "172.240.0.0/16",
      "size" : 24
    }
  ]
}
```

3\. ใช้คำสั่งรัน docker daemon

```
sudo dockerd
```

4\. รีสตาร์ทเครื่อง

```
sudo reboot
```

ตรวจสอบ subnet ด้วยคำสั่ง sudo netstat -rn จะพบว่า subnet ถูกเปลี่ยนจาก 172.17.0.0 ไปเป็น 172.240.0.0 ดังรูป

[![image.png](https://arit-manual.nstru.ac.th/uploads/images/gallery/2023-07/scaled-1680-/BXjimage.png)](https://arit-manual.nstru.ac.th/uploads/images/gallery/2023-07/BXjimage.png)

# Tips and Trick

### การทำให้ container สามารถใช้งาน sudo ได้

```
apt-get install sudo
```

### การเข้าใช้งาน container โดยใช้ user root

```
sudo docker exec -it --user root container_name /bin/bash
```

# การใช้ Docker ทำ Load Balance ให้กับเว็บไซต์หรือระบบ โดยใช้ Nginx Container

### การตั้งค่า Nginx

ตั้งค่า default-ssl.conf สำหรับกำหนด upstream สำหรับรองรับ Load balance ดังนี้

```
upstream my_app {
    server app_php:80;

    keepalive 32;
}

server {
    listen 443;
    server_name yourdomain;

    location / {
        proxy_pass http://my_app/;

        proxy_http_version 1.1;
        proxy_set_header Connection "";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For
            $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 300s;
        proxy_send_timeout 300s;

        index index.php index.html index.htm;
    }    
}
```

### ตัวอย่างการตั้งค่า Docker compose

สามารถกำหนด docker-compose.yml ได้ดังนี้

```
services:
    app_php:
        build:
            context: php74
        image: app
        restart: always
        expose:
            - "80"
            - "443"            

    nginx:
        image: nginx:1.17
        container_name: ngx
        restart: always
        ports:
            - 80:80
            - 443:443
        depends_on:
            - app_php
```

หรือกรณีที่มีการใช้ Network ร่วมกับ Docker Compose อื่นสามารถกำหนด docker-compose.yml ได้ดังนี้

```
version: '3'
networks:
  mynetwork:
    external: true
    name: test_mynetwork
services:
    app_php:
        build:
            context: php74
        image: app
        restart: always
        expose:
            - "80"
            - "443"            
        networks:
            - mynetwork 

    nginx:
        image: nginx:1.17
        container_name: ngx
        restart: always
        ports:
            - 80:80
            - 443:443
        depends_on:
            - app_php
```

### ขยาย Docker container สำหรับกระจายโหลด

รัน docker compose เพื่อขยาย container สำหรับกระจายโหลดด้วยคำสั่งต่อไปนี้

```
sudo docker compose up -d --scale app_php=3
```

คำสั่งนี้มีความหมายว่าให้สร้าง container app\_php จำนวน 3 container

หรือสามารถกำหนดการขยาย container ไว้ใน Docker compose ได้ดังนี้

```
services:
    app_php:
        build:
            context: php74
        image: app
        restart: always
        deploy:
            replicas: 3
        expose:
            - "80"
            - "443"            

    nginx:
        image: nginx:1.17
        container_name: ngx
        restart: always
        ports:
            - 80:80
            - 443:443
        depends_on:
            - app_php
```

### ทดสอบการทำงานของ Load Balance

หากใช้ภาษา php ให้สร้างไฟล์สำหรับรันโค้ดต่อไปนี็

```
header('Content-Type: application/json');
header('Cache-Control: no-store');

echo json_encode([
    'container' => gethostname(),
    'server_time' => date('Y-m-d H:i:s'),
    'server_ip' => $_SERVER['SERVER_ADDR'] ?? '',
]);
```

หากพบว่า Load balance ไม่ทำงานให้ลองรันคำสั่งเพื่อโหลด Nginx ใหม่ดังนี้

```
docker exec ngx nginx -t
docker exec ngx nginx -s reload
```