docker: Docker Engine API(Docker daemon)
개요
- 공식 문서
- Docker 데몬(dockerd)은 HTTP RESTful API(Docker Engine API)를 통해 모든 기능을 제어
dockerCLI 자체도 내부적으로 이 API를 사용- SDK(Go, Python)와 HTTP API 두 가지 방식으로 사용 가능
- SDK는 하위 버전 호환 — API 버전 협상(
WithAPIVersionNegotiation) 지원
| 접근 방식 | 설명 |
|---|---|
| Unix Socket | 로컬 기본 방식 — /var/run/docker.sock |
| TCP | 원격 접속 — 별도 설정 필요 (TLS 적용 강력 권장) |
| Go SDK | github.com/docker/docker/client — 타입 안전 API |
| Python SDK | docker 패키지 — 스크립트·자동화에 적합 |
HTTP API
- 최신 버전 레퍼런스
- 버전별 변경 이력
- API 버전은 URL 경로에 포함:
/v{version}/{endpoint} -
현재 데몬의 API 버전 확인:
docker version --format ''
Unix Socket 호출
# 이미지 목록
curl --unix-socket /var/run/docker.sock http://localhost/v1.41/images/json
# 컨테이너 목록 (실행 중)
curl --unix-socket /var/run/docker.sock http://localhost/v1.41/containers/json
# 데몬 정보
curl --unix-socket /var/run/docker.sock http://localhost/v1.41/info
TCP 호출 (원격 접속 설정 후)
curl -X GET http://127.0.0.1:3000/v1.41/images/json
SDK
Go SDK
go get github.com/docker/docker/client
- 레퍼런스
- 클라이언트 생성:
cli, err := client.NewClientWithOpts(
client.FromEnv,
client.WithAPIVersionNegotiation(),
)
client.FromEnv:DOCKER_HOST,DOCKER_TLS_VERIFY,DOCKER_CERT_PATH환경변수 참조- 원격 접속 시:
client.WithHost("tcp://127.0.0.1:3000")
Python SDK
pip install docker
import docker
client = docker.from_env()
images = client.images.list()
for img in images:
print(img.id)
원격 접속 설정
Docker 데몬은 기본적으로 Unix Socket만 리슨 — TCP 원격 접속을 위해 추가 설정 필요.
주의: TCP를 평문으로 열면 보안 위험이 있습니다. 운영 환경에서는 반드시 TLS 인증서를 적용하세요.
systemd 서비스 수정
# /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd \
-H fd:// \
--containerd=/run/containerd/containerd.sock \
-H tcp://0.0.0.0:3000
systemctl daemon-reload
systemctl restart docker
daemon.json 으로 설정 (권장)
# /etc/docker/daemon.json
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:3000"]
}
# 단, systemd 서비스의 -H 옵션과 중복 설정 시 충돌 주의
# /lib/systemd/system/docker.service 에서 -H fd:// 제거 필요
TLS 원격 접속 (권장)
# 클라이언트 환경변수 설정
export DOCKER_HOST=tcp://<server-ip>:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker/certs
주요 API 엔드포인트
| 리소스 | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 이미지 | GET | /images/json |
이미지 목록 |
| 이미지 | POST | /images/create |
이미지 pull |
| 이미지 | DELETE | /images/{name} |
이미지 삭제 |
| 컨테이너 | GET | /containers/json |
컨테이너 목록 |
| 컨테이너 | POST | /containers/create |
컨테이너 생성 |
| 컨테이너 | POST | /containers/{id}/start |
컨테이너 시작 |
| 컨테이너 | POST | /containers/{id}/stop |
컨테이너 중지 |
| 컨테이너 | POST | /containers/{id}/wait |
컨테이너 상태 대기 |
| 컨테이너 | GET | /containers/{id}/logs |
컨테이너 로그 |
| 컨테이너 | DELETE | /containers/{id} |
컨테이너 삭제 |
| 볼륨 | GET | /volumes |
볼륨 목록 |
| 네트워크 | GET | /networks |
네트워크 목록 |
| 시스템 | GET | /info |
데몬 정보 |
| 시스템 | GET | /version |
API 버전 정보 |
예제
이미지 목록 조회
HTTP
curl -X GET http://127.0.0.1:3000/v1.41/images/json
Go SDK
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
)
func main() {
ctx := context.Background()
cli, err := client.NewClientWithOpts(
client.WithHost("tcp://127.0.0.1:3000"),
client.WithAPIVersionNegotiation(),
)
if err != nil {
panic(err)
}
defer cli.Close()
images, err := cli.ImageList(ctx, image.ListOptions{})
if err != nil {
panic(err)
}
for _, img := range images {
fmt.Println(img.ID)
}
}
컨테이너 생성·실행·로그·삭제
HTTP
# 1. 이미지 pull
curl -X POST "http://127.0.0.1:3000/v1.41/images/create?fromImage=alpine:3.16.0"
# 2. 컨테이너 생성 → 응답 예: {"Id":"ac6594faf5","Warnings":[]}
curl -H "Content-Type: application/json" \
-d '{"Image": "alpine:3.16.0", "Cmd": ["echo", "hello world"]}' \
-X POST http://127.0.0.1:3000/v1.41/containers/create
# 3. 컨테이너 시작
curl -X POST http://127.0.0.1:3000/v1.41/containers/ac6594faf5/start
# 4. 종료 대기
curl -X POST "http://127.0.0.1:3000/v1.41/containers/ac6594faf5/wait?condition=not-running"
# 5. 로그 확인
curl -X GET "http://127.0.0.1:3000/v1.41/containers/ac6594faf5/logs?stdout=1"
# 6. 컨테이너 삭제
curl -X DELETE http://127.0.0.1:3000/v1.41/containers/ac6594faf5
Go SDK
package main
import (
"context"
"io"
"os"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
)
func main() {
ctx := context.Background()
cli, err := client.NewClientWithOpts(
client.WithHost("tcp://127.0.0.1:3000"),
client.WithAPIVersionNegotiation(),
)
if err != nil {
panic(err)
}
defer cli.Close()
// 1. 이미지 pull
rc, err := cli.ImagePull(ctx, "alpine:3.16.0", image.PullOptions{})
if err != nil {
panic(err)
}
defer rc.Close()
io.Copy(os.Stdout, rc)
// 2. 컨테이너 생성
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "alpine:3.16.0",
Cmd: []string{"echo", "hello world"},
}, nil, nil, nil, "")
if err != nil {
panic(err)
}
// 3. 컨테이너 시작
if err := cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
panic(err)
}
// 4. 종료 대기
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
panic(err)
}
case <-statusCh:
}
// 5. 로그 출력
logRC, err := cli.ContainerLogs(ctx, resp.ID, container.LogsOptions{ShowStdout: true})
if err != nil {
panic(err)
}
stdcopy.StdCopy(os.Stdout, os.Stderr, logRC)
// 6. 컨테이너 삭제
if err := cli.ContainerRemove(ctx, resp.ID, container.RemoveOptions{}); err != nil {
panic(err)
}
}