Docker compose là gì ? Kiến thức cơ bản về Docker compose

0
47
Rate this post

I. Docker compose là gì ?

Docker compose là công cụ giúp bạn xác định và chạy nhiều container trong một ứng dụng Docker. Bằng việc sử dụng compose, bạn có thể cấu hình các dịch vụ trong ứng dụng của bạn bằng cách sử dụng tệp YAML và sau đó sử dụng các lệnh để tạo và chạy các container dựa trên cấu hình đó. Việc sử dụng compose khá đơn giản chỉ với ba bước:

  • Khai báo môi trường ứng dụng trong Dockerfile.
  • Khai báo các dịch vụ cần thiết để chạy ứng dụng trong tệp docker-compose.yml.
  • Chạy lệnh docker-compose up để khởi động và chạy ứng dụng.

II. Tính năng chính

Tính năng của Docker compose

Không giống như Dockerfile (dùng để build các image), Docker compose được sử dụng để build và chạy các container. Các thao tác của docker-compose tương tự như lệnh docker run.

Docker compose cho phép tạo nhiều service (container) giống nhau bằng lệnh:

$ docker-compose scale <tên service> = <số lượng>

III. Hướng dẫn cài đặt

1. Thiết lập ứng dụng web:

  • Sử dụng npm:
npm init react-app <tên app>
  • Hoặc sử dụng yarn:
yarn create react-app <tên app>

Trong bài demo này, chúng ta sẽ sử dụng React JS.

  • Thay đổi file App.js:
import React, { useState } from 'react';
import './App.css';

function status(response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
  } else {
    return Promise.reject(new Error(response.statusText))
  }
}

function json(response) {
  return response.json()
}

const getFoodDetail = (foodId) => {
  return fetch(
    "http://localhost:8080/api/v1/foods?id=" + foodId,
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json; charset=UTF-8"
      }
    }
  )
  .then(status)
  .then(json)
  .then(res => (new Promise((resolve, reject) => resolve(res.data))))
  .catch(err => {
    alert("err: ", err);
    return undefined;
  });
};

function App() {
  const [foodId, setFoodId] = useState(0);
  const [dataFood, setDataFood] = useState("");

  return (
    <div className="App">
      <header className="App-header">
        <h3 color="while">App tìm món ăn theo id</h3>
        <div>
          <input className="input" name="id" placehodler="Nhập id" onChange={(e) => setFoodId(e.target.value)}/>
          <button className="btnSearch" onClick={() => { getFoodDetail(foodId).then(data => setDataFood(data)) }}>
            Tìm kiếm
          </button>
          <p style={{textAlign: "left"}}>Kết quả: {dataFood}</p>
        </div>
      </header>
    </div>
  );
}

export default App;
  • Thay đổi file App.css:
.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.input {
  padding: 10px;
  width: 200px;
  border: 0;
  box-shadow: 0px 2px 30px 0px rgba(255,255,15,1);
  margin-right: 10px;
}

.btnSearch {
  padding: 10px 50px;
  color: white;
  background: blueviolet;
  border: 0;
  border-radius: 20px;
}

.btnSearch:hover {
  background: #c837de;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

2. Thiết lập server:

  • File main.go:
package main

import (
    "net/http"
    "strconv"

    "github.com/gin-gonic/gin"
)

func Options(c *gin.Context) {
    if c.Request.Method != "OPTIONS" {
        c.Next()
    } else {
        c.Header("Access-Control-Allow-Origin", "*")
        c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
        c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
        c.Header("Allow", "HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS")
        c.Header("Content-Type", "application/json")
        c.AbortWithStatus(200)
    }
}

func Secure(c *gin.Context) {
    c.Header("Access-Control-Allow-Origin", "*")
}

type Foods map[int]string

var foods = Foods{
    1: "Gà kho xả ớt",
    2: "Cá lóc kho",
    3: "Thịt xào măng",
    4: "Bún chả cá",
}

func getFoodById(c *gin.Context) {
    id, err := strconv.Atoi(c.Query("id"))
    if err != nil {
        c.JSON(http.StatusOK, gin.H{"error": err.Error()})
    }

    if len(foods[id]) > 0 {
        c.JSON(http.StatusOK, gin.H{"data": foods[id]})
    } else {
        c.JSON(http.StatusOK, gin.H{"data": "Không tìm thấy"})
    }
}

func main() {
    r := gin.Default()
    r.Use(Options)
    r.Use(Secure)

    v1 := r.Group("/api/v1")
    {
        v1.GET("/foods", getFoodById)
    }

    r.Run(":8080")
}

3. Cấu hình Dockerfile

Nếu bạn không quen thuộc với việc cấu hình Dockerfile, đừng lo lắng! Hãy xem lại phần 1 tại đây để biết thêm thông tin chi tiết.

FROM node:carbon-alpine AS node_builder

WORKDIR /app/webreactjs
COPY /webreactjs/package.json .
RUN npm install

COPY /webreactjs .

LABEL name="webreactjs" version="1.0"

EXPOSE 3000

CMD ["npm", "start"]



FROM golang:1.11 AS go_builder

ADD . /app
WORKDIR /app

RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-w" -a -o /main .

LABEL name="server" version="1.0"



FROM alpine:latest

RUN apk -no-cache add ca-certificates

COPY --from=go_builder /main ./
RUN chmod +x ./main

EXPOSE 8080

CMD ./main

4. Cấu hình docker-compose.yml

version: '2.1'

services:
  webreactjs:
    image: af1205224676
    build: .
    ports:
      - 3000:3000
    restart: always

  servergo:
    image: cef5deda0834
    build: .
    ports:
      - 8080:8080
    restart: always

Trong file docker-compose.yml, chúng ta thiết lập các dịch vụ (containers) cần cài đặt và chạy.

  • version: chỉ ra phiên bản của docker-compose đã sử dụng.
  • services: thiết lập các dịch vụ (containers) cần cài đặt và chạy.
  • image: chỉ ra image được sử dụng để tạo container.
  • build: dùng để tạo container từ Dockerfile.
  • ports: thiết lập cổng chạy trên máy chủ và trong container.
  • restart: tự động khởi động lại container khi nó bị tắt.

Ngoài ra, còn có một số lệnh config khác như environment để thiết lập biến môi trường, depends_on để chỉ ra sự phụ thuộc giữa các dịch vụ, và volumes để mount các thư mục giữa máy chủ và container.

  • Chạy lệnh sau để khởi động ứng dụng:
$ docker-compose up

Sau khi chạy xong, bạn sẽ thấy docker-compose đã khởi động và chạy hai dịch vụ mà chúng ta đã cấu hình trong file docker-compose.yml.

Docker compose

Hãy ngắm nhìn thành quả:

Docker compose

Web

Server

Mẹo nhỏ

Đối với những bạn sử dụng Visual Studio Code, bạn có thể nhanh chóng tạo các config cho Dockerfile và docker-compose.yml chỉ bằng một vài thao tác đơn giản. Cài đặt extension Docker trên Visual Studio Code và sau đó nhấn F1, gõ “docker: add” và chọn mẫu tạo có sẵn kèm theo cấu hình port. Visual Studio Code sẽ tự động tạo các file Dockerfile, docker-compose.yml, docker-compose.debug.yml và .dockerignore cho bạn. Ngoài ra, extension còn cung cấp gợi ý lệnh và cảnh báo khi bạn tự cấu hình các file Docker, rất tiện lợi.

Đây là bản dịch và chỉnh sửa từ bài viết gốc của dnulib.edu.vn. Để biết thêm chi tiết, hãy truy cập dnulib.edu.vn