Docker Compose

Mon 1 May 2023
ใช้เวลาอ่าน 2 นาที
Featured Image

ตัวอย่างสำหรับตอนนี้เราสามารถ copy file จากตอนที่แล้วมาได้เลยคือสามารถ Dockerfile เดิมได้เลยแล้วสร้าง file docker-compose.yml เพิ่มขึ้นมาดังนี้

docker-compose.yml


version: '3'

services:
  fastapi:
    build:
      context: ../.devcontainer
      dockerfile: Dockerfile
    volumes:
      - ../:/workspace/ep4:cached
    init: true
    command: [ 'sleep', 'infinity' ]

networks:
  default:
    name: ep4

build

จากตัวอย่างด้านบนผมสร้าง service ขื่อ fastapi และกำหนดให้ build โดยชี้ context ไปยัง ../.devcontainer และ dockerfile ชี้ไปยัง Dockerfile ตรงนี้ผมเขียนแบบเต็มเพื่อให้ดูเป็นตัวอย่างนะครับ ปกติถ้าใช้ dockerfile ขื่อ Dockerfile เรากำหนดแค่ build ได้เลย


fastapi:
    build: ../.devcontainer

ที่เขียนแบบเต็มให้ดูเพราะบางครั้งเราอาจจะเปลี่ยนชื่อ file เช่น Dockerfile.dev Dockerfile.vscode เป็นต้น และที่สังเกตเห็นอีกอย่างคือการอ้างอิง path Dev Container จะอ้างอิง path จาก root directory ของ project ดังนั้นมันถึงต้องถอยออกไปหนึ่งชั้นนั่นเอง ตรงนี้ต้องจำให้ดีนะเพราะพอสูงขึ้นไปอีกหน่อยจะมีการอ้างอิงแบบนี้อีก เช่นการ Extend docker-compose การ copy file ใน Dockerfile เป็นต้น ซึ่งจะกล่าวในตอนต่อ ๆ ไปอีกครั้ง

volumes

ส่วน volumes เราต้องสั่งให้ขี้เองว่าจะ mount ไปไว้ที่ไหนกำหนดได้ตามชอบ จากตัวอย่างตอนก่อน ๆ ถ้าสังเกตจะพบว่ามันจะ mount อัตโนมัติให้ที่ /workspace/projectname ตอนนี้เราตั้งที่ไหนก็ได้ แต่ต้องให้สัมพันธ์กับ file devcontainer.json ที่จะกล่าวต่อไปด้วย

command

ปกติเราจะตั้งให้เปิดคำสั่งที่ run แบบ background ทิ้งไว้เพื่อไม่ให้ container หยุดทำงานหลังจาก up ขึ้นที่นิยมก็จะเป็น sleep แบบ infinity

network

ตรงนี้ตั้งหรือไม่ก็ได้ถ้าตั้งไว้ก็จะสังเกตง่ายหน่อยเวลาเราไป list ดูว่ามี network อะไรบ้างในระบบจะได้ไม่สับสนด้วย

devcontainer.json

สำหรับ settings ใน devcontainer.json ก็ให้เปลี่ยนจาก build เป็นดังนี้


"dockerComposeFile": [
    "docker-compose.yml"
],
"service": "fastapi",
"workspaceFolder": "/workspace/ep4"

การอ้างอิง path ตรงนี้สามารถ ralative กับ .devcontainer ได้เลย และเพิ่มอีกสอง properties คือ

  • service ต้องระบุให้ตรงกับ docker-compose.yml
  • workspaceFolder คือจุด mount ของ volume ใน docker-compose.yml นั่นเองเมื่อ up ขึ้นมาก็จะทำงานที่นี่

file เต็ม


{
  "name": "Dev Container EP4",
  "dockerComposeFile": [
    "docker-compose.yml"
  ],
  "service": "fastapi",
  "workspaceFolder": "/workspace/ep4",
  "init": true,
  "customizations": {
    "vscode": {
      "settings": {
        "editor.autoClosingBrackets": "always",
        "editor.bracketPairColorization.enabled": true,
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.formatOnSaveMode": "file",
        "editor.guides.bracketPairs": true,
        "editor.guides.highlightActiveIndentation": false,
        "editor.guides.indentation": false,
        "editor.inlineSuggest.enabled": true,
        "editor.minimap.enabled": false,
        "editor.tabSize": 2,
        "indentRainbow.indicatorStyle": "light",
        "python.formatting.provider": "none",
        "remote.autoForwardPorts": true,
        "remote.localPortHost": "allInterfaces",
        "terminal.integrated.cursorBlinking": true,
        "terminal.integrated.defaultProfile.linux": "fish",
        "vsintellicode.features.python.deepLearning": "enabled",
        "workbench.colorCustomizations": {
          "editorUnnecessaryCode.border": "#fbbd52",
          "editorUnnecessaryCode.opacity": "#ffffff8b",
          "editorIndentGuide.background": "#2a2a2a"
        },
        "editor.showUnused": true,
        "editor.renderLineHighlight": "gutter",
        "terminal.integrated.gpuAcceleration": "on",
        "terminal.integrated.copyOnSelection": true,
        "terminal.integrated.cursorStyle": "line",
        "terminal.integrated.fontSize": 15,
        "editor.quickSuggestions": {
          "other": "on",
          "comments": "on",
          "strings": "on"
        },
        "isort.check": true,
        "indentRainbow.lightIndicatorStyleLineWidth": 2,
        "python.languageServer": "Pylance",
        "python.linting.banditEnabled": true,
        "python.linting.lintOnSave": true,
        "python.linting.enabled": true,
        "python.linting.pylintEnabled": false,
        "[python]": {
          "editor.defaultFormatter": "ms-python.autopep8",
          "editor.formatOnSave": true,
          "editor.formatOnType": true,
          "editor.tabSize": 4,
          "editor.codeActionsOnSave": {
            "source.organizeImports": true
          }
        },
        "isort.args": [
          "--profile",
          "black"
        ],
        "python.analysis.autoImportCompletions": true,
        "python.analysis.autoImportUserSymbols": true,
        "python.analysis.indexing": true,
        "python.analysis.diagnosticSeverityOverrides": {
          "reportUnboundVariable": "information",
          "reportImplicitStringConcatenation": "warning",
          "reportImportCycles": "error",
          "reportUnusedCoroutine": "error"
        },
        "python.formatting.autopep8Args": [
          "--max-line-length",
          "150",
          "--experimental"
        ]
      },
      "extensions": [
        "kevinrose.vsc-python-indent",
        "ms-python.autopep8",
        "ms-python.isort",
        "njpwerner.autodocstring",
        "oderwat.indent-rainbow",
        "VisualStudioExptTeam.vscodeintellicode"
      ]
    }
  }
}

ส่งท้าย

หลัก ๆ Docker Compose ก็จะคล้าย ๆ กับ Dockefile ตอนเลือกใช้ก็ต้องดูว่า Project ของเราเป็นแค่เดี่ยว ๆ หรือ เป็นชุด ถ้าเป็นขุดปกติเราก็ทำ docker-compose.yml ไว้อยู่แล้วตอน dev อาจจะ extend ออกมาก็ได้ หรือ จะทำ Docker Compose ของแต่ละ Project ไว้แล้วเชื่อมด้วยกันกับ COMPOSE_PROJECT_NAME ก็ได้ไว้มีโอกาสจะแนะนำให้อีกที

ตอนต่อไปถ้าไม่มีอะไรผิดพลาดจะมาแนะนำเรื่องการจัดการ user และ sudo กัน

ก่อนหน้า Dockerfile
comments powered by Disqus