๐Ÿณ DinD vs DooD: Docker ๊ธฐ๋ฐ˜ Jenkins/Argo CI/CD ์ „๋žต ๋ถ„์„

Docker ๊ธฐ๋ฐ˜์˜ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•  ๋•Œ, Jenkins๋‚˜ Argo ๊ฐ™์€ ์ž๋™ํ™” ๋„๊ตฌ์—์„œ Docker๋ฅผ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ• ์ง€์— ๋”ฐ๋ผ DinD(Docker-in-Docker) ์™€ DooD(Docker-outside-of-Docker) ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹ ์ค‘ ์„ ํƒํ•˜๊ฒŒ ๋œ๋‹ค.

DinD (Docker-in-Docker)

graph TD
  Host[Host Machine]
	subgraph OuterDinD ["Outer ์ปจํ…Œ์ด๋„ˆ(๋„์ปค ๋ฐ๋ชฌ ์‹คํ–‰ ์ค‘)"]
	  Inner1["Inner ์ปจํ…Œ์ด๋„ˆ 1"]
	  Inner2["Inner ์ปจํ…Œ์ด๋„ˆ 2"]
	end

  Host --> |previleged ๊ถŒํ•œ ๋ถ€์—ฌ| OuterDinD

  classDef outer fill:#44f,stroke:#fff,stroke-width:2px;
  classDef inner fill:#88f,stroke:#333,stroke-width:1px;
  classDef host fill:#000,stroke:#000,stroke-width:2px;

  class Host host;
  class OuterDinD outer;
  class Inner1,Inner2 inner;

dind

์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ์ž์ฒด์ ์œผ๋กœ Docker ๋ฐ๋ชฌ์„ ์‹คํ–‰ํ•˜์—ฌ, ์™„์ „ํ•œ ๊ฒฉ๋ฆฌ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, Jenkins Job์ด ์‹คํ–‰๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ๋…๋ฆฝ์ ์ธ Docker ๋ฐ๋ชฌ์„ ๊ตฌ๋™ํ•˜์—ฌ, ๊ทธ ์•ˆ์—์„œ ๋‹ค์‹œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์™„์ „ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ ์ž ํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ โ€”privileged ๊ถŒํ•œ์ด ํ•„์š”ํ•˜๋ฉฐ, ๋ณด์•ˆ์ƒ ์œ„ํ—˜์ด ์กด์žฌํ•˜๊ณ  ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰์ด ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค.

DooD (Docker-outside-of-Docker)

graph TD
	Host["Host Machine"]
  subgraph Group1 [๋ณ‘๋ ฌ ์‹คํ–‰]
	  Pararrel1["Inner ์ปจํ…Œ์ด๋„ˆ 1"]
	  OuterDooD["Outer ์ปจํ…Œ์ด๋„ˆ (docker CLI ์‚ฌ์šฉ, ๋„์ปค๋ฐ๋ชฌ ์—†์Œ)"]
	  Pararrel2["Inner ์ปจํ…Œ์ด๋„ˆ 2"]
	end
  

  Host --> |docker.sock๋งŒ ๊ณต์œ | OuterDooD
  

  classDef outer fill:#44f,stroke:#fff,stroke-width:2px;
  classDef inner fill:#44f,stroke:#333,stroke-width:1px;
  classDef host fill:#000,stroke:#000,stroke-width:2px;

  class Host host;
  class OuterDooD outer;
  class Pararrel1,Pararrel2 inner;

dood

์ปจํ…Œ์ด๋„ˆ์—์„œ ํ˜ธ์ŠคํŠธ์˜ Docker ์†Œ์ผ“(/var/run/docker.sock)์„ ๊ณต์œ ํ•˜์—ฌ Docker ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

์ฆ‰, Jenkins๋‚˜ Argo์˜ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ˜ธ์ŠคํŠธ์˜ Docker ๋ฐ๋ชฌ์— ์ ‘๊ทผํ•˜์—ฌ ์ง์ ‘ Docker ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ์„ค์ •์ด ๊ฐ„๋‹จํ•˜๊ณ  ์„ฑ๋Šฅ์ด ์šฐ์ˆ˜ํ•˜์ง€๋งŒ, ํ˜ธ์ŠคํŠธ์˜ Docker ๊ถŒํ•œ์„ ๊ณต์œ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ์ƒ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋น„๊ต ๋ถ„์„: DinD vs DooD

๊ตฌ๋ถ„ DinD (Docker-in-Docker) DooD (Docker-outside-of-Docker)
์‹คํ–‰ ๋ฐฉ์‹ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ Docker ๋ฐ๋ชฌ ๊ตฌ๋™ ํ˜ธ์ŠคํŠธ Docker ์†Œ์ผ“์„ ๊ณต์œ 
๊ถŒํ•œ ํ•„์š” โ€”privileged ๊ถŒํ•œ ํ•„์š” ์†Œ์ผ“ ๋งˆ์šดํŠธ๋งŒ์œผ๋กœ ๊ฐ€๋Šฅ
๊ฒฉ๋ฆฌ์„ฑ ์™„์ „ํ•œ ๊ฒฉ๋ฆฌ (ํ…Œ์ŠคํŠธ์šฉ ์œ ๋ฆฌ) ํ˜ธ์ŠคํŠธ์™€ ๊ณต์œ  (์†๋„ ๋น ๋ฆ„)
๋ณด์•ˆ์„ฑ ๋‚ฎ์Œ (๊ถŒํ•œ ๋†’์Œ) ์†Œ์ผ“ ๊ณต์œ  ์œ„ํ—˜ ์กด์žฌ
์„ฑ๋Šฅ ๋А๋ฆด ์ˆ˜ ์žˆ์Œ (๋‚ด๋ถ€ ๋ฐ๋ชฌ) ๋น ๋ฆ„ (ํ˜ธ์ŠคํŠธ ์ง์ ‘ ์‹คํ–‰)
๋Œ€ํ‘œ ์‚ฌ์šฉ ์‚ฌ๋ก€ ํ…Œ์ŠคํŠธ ์ปจํ…Œ์ด๋„ˆ ๋ถ„๋ฆฌ, Lab ํ™˜๊ฒฝ ์‹ค์ „ ๋ฐฐํฌ, Docker ๋นŒ๋“œ/ํ‘ธ์‹œ

Jenkins์—์„œ์˜ ํ™œ์šฉ

DooD ๋ฐฉ์‹

docker run \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v $(pwd):/workspace \
  jenkins/jenkins:lts
  • Jenkins ์ปจํ…Œ์ด๋„ˆ๋Š” ํ˜ธ์ŠคํŠธ์˜ Docker ์—”์ง„์— ์ ‘๊ทผ
  • docker build, docker push ๋“ฑ ์‰ฝ๊ฒŒ ์‹คํ–‰ ๊ฐ€๋Šฅ
  • ์ฃผ์˜: ํ˜ธ์ŠคํŠธ์˜ Docker ์ „์ฒด ๊ถŒํ•œ์„ ๊ณต์œ ๋ฐ›์Œ โ†’ ๋ณด์•ˆ ๊ณ ๋ ค ํ•„์š”

DinD ๋ฐฉ์‹

docker run --privileged \
  -v $(pwd):/workspace \
  docker:dind
  • Jenkins Job์—์„œ ์ž์ฒด Docker ๋ฐ๋ชฌ ๊ตฌ๋™
  • ๊ฒฉ๋ฆฌ๋œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๊ตฌ์„ฑ์— ์ ํ•ฉ
  • ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰์ด ๋งŽ๊ณ  ๋ณด์•ˆ ๋ฆฌ์Šคํฌ ์กด์žฌ

Argo Workflow์—์„œ์˜ ํ™œ์šฉ

DooD ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ ์˜ˆ์‹œ

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: dood-example-
spec:
  entrypoint: docker-job
  templates:
    - name: docker-job
      container:
        image: docker
        command: ["docker", "build", "-t", "myimage", "."]
        volumeMounts:
          - name: docker-socket
            mountPath: /var/run/docker.sock
  volumes:
    - name: docker-socket
      hostPath:
        path: /var/run/docker.sock
  • ํ˜ธ์ŠคํŠธ์˜ Docker ์†Œ์ผ“ ๊ณต์œ 
  • ๋น ๋ฅธ ๋นŒ๋“œ, ๋ฐฐํฌ ์ž‘์—…์— ์ ํ•ฉ

DinD ๊ธฐ๋ฐ˜ ๊ตฌ์„ฑ ์˜ˆ์‹œ

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: dind-example-
spec:
  entrypoint: docker-job
  templates:
    - name: docker-job
      container:
        image: docker:dind
        securityContext:
          privileged: true
        command: ["dockerd-entrypoint.sh"]
  • ๋…๋ฆฝ์ ์ธ Docker ๋ฐ๋ชฌ ์‹คํ–‰
  • ๊ฒฉ๋ฆฌ๋œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์— ์ ํ•ฉํ•˜๋‚˜ ๋ณด์•ˆ/์ž์› ์ด์Šˆ ๊ณ ๋ ค ํ•„์š”

์ •๋ฆฌ

  • DooD๋Š” ์†๋„์™€ ๊ฐ„ํŽธํ•จ์„ ์ค‘์‹œํ•  ๋•Œ ์‚ฌ์šฉ
  • DinD๋Š” ๊ฒฉ๋ฆฌ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๋…๋ฆฝ์„ฑ์ด ์ค‘์š”ํ•  ๋•Œ ์‚ฌ์šฉ
  • Jenkins, Argo ํ™˜๊ฒฝ ๋ชจ๋‘ ๋ชฉ์ ์— ๋”ฐ๋ผ ๋‘ ๋ฐฉ์‹์„ ์„ ํƒ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ