Docker SDK를 활용한 Go 컨테이너 리소스 제한

컨테이너 생성 시 리소스 제한

package main

import (
    "context"
    "log"
    "os"

    docker "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/container"
    "github.com/docker/docker/api/types/mount"
    "github.com/docker/docker/client"
    "github.com/docker/go-connections/nat"
)

func main() {
    dockerHost := "tcp://docker-host:2376"
    dockerClient, err := client.NewClientWithOpts(
        client.WithHost(dockerHost),
        client.WithAPIVersionNegotiation(),
    )
    if err != nil {
        log.Fatal("Docker 클라이언트 생성 실패:", err)
    }
    defer dockerClient.Close()

    nginxConfig := &container.Config{
        Image: "nginx:alpine",
    }

    resourceLimits := container.Resources{
        Memory:     268435456,  // 256MB
        MemorySwap: 268435456,
        CPUPeriod:  100000,
        CPUQuota:   100000,     // 1 core
    }

    hostSettings := &container.HostConfig{
        RestartPolicy: container.RestartPolicy{Name: "always"},
        PortBindings: nat.PortMap{
            "80/tcp": []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: "8080"}},
        },
        Mounts: []mount.Mount{
            {
                Type:   mount.TypeBind,
                Source: "/app/web",
                Target: "/usr/share/nginx/html",
            },
        },
        Resources: resourceLimits,
    }

    containerName := "web-server"
    newContainer, err := dockerClient.ContainerCreate(
        context.Background(),
        nginxConfig,
        hostSettings,
        nil,
        nil,
        containerName,
    )
    if err != nil {
        log.Fatal("컨테이너 생성 실패:", err)
    }

    if err := dockerClient.ContainerStart(
        context.Background(),
        newContainer.ID,
        docker.ContainerStartOptions{},
    ); err != nil {
        log.Fatal("컨테이너 시작 실패:", err)
    }

    log.Println("컨테이너 생성 완료 ID:", newContainer.ID)
}

실행 중인 컨테이너 리소스 갱신

package main

import (
    "context"
    "log"
    "os"

    "github.com/docker/docker/api/types/container"
    "github.com/docker/docker/client"
)

func main() {
    dockerClient, err := client.NewClientWithOpts(
        client.WithHost("tcp://docker-host:2376"),
        client.WithAPIVersionNegotiation(),
    )
    if err != nil {
        log.Fatal("Docker 클라이언트 생성 실패:", err)
    }
    defer dockerClient.Close()

    targetContainer := "web-server"
    newLimits := container.Resources{
        Memory:     536870912,  // 512MB
        MemorySwap: 536870912,
        CPUQuota:   200000,     // 2 cores
        CPUPeriod:  100000,
    }

    updateConfig := container.UpdateConfig{
        Resources: newLimits,
    }

    response, err := dockerClient.ContainerUpdate(
        context.Background(),
        targetContainer,
        updateConfig,
    )
    if err != nil {
        log.Fatal("리소스 갱신 실패:", err)
    }

    log.Println("리소스 제한 갱신 완료:", response.Warnings)
}

container.Resources 구조체 상세

  1. CPUShares (int64): CPU 자원 배분 가중치
  2. Memory (int64): 최대 메모리 사용량(바이트)
  3. NanoCPUs (int64): CPU 할당량(10-9 단위)
  4. CgroupParent (string): 상위 cgroup 경로
  5. BlkioWeight (uint16): 블록 IO 가중치
  6. CPUPeriod (int64): CPU 할당 주기(마이크로초)
  7. CPUQuota (int64): CPU 할당량(마이크로초)
  8. CpusetCpus (string): 할당할 CPU 코어 지정
  9. MemorySwap (int64): 메모리+Swap 총 한계
  10. MemorySwappiness (*int64): 스왑 사용 선호도
  11. OomKillDisable (*bool): OOM Killer 비활성화
  12. PidsLimit (*int64): 최대 프로세스 수
  13. Ulimits ([]*units.Ulimit): 시스템 리소스 제한
  14. DeviceCgroupRules ([]string): 디바이스 cgroup 규칙
  15. IOMaximumBandwidth (uint64): 최대 IO 대역폭(Windows)

각 필드는 Docker 버전 및 OS 환경에 따라 동작이 상이할 수 있음

태그: docker go 컨테이너 리소스제한 Docker-SDK

7월 20일 21:46에 게시됨