728x90
๋ฐ˜์‘ํ˜•

15์žฅ ๋ณด์•ˆ ์›๊ฒฉ ์ ‘๊ทผ ๋ฐ CI/CD๋ฅผ ์œ„ํ•œ ๋„์ปค ์„ค์ •

๋„์ปค ์—”์ง„๊ณผ API ๋ถ„๋ฆฌ์‹œ ์ปจํ…Œ์ด๋„ˆ ๋„๊ตฌ์˜ ์„ ํƒ์ง€๊ฐ€ ๋„“์–ด์ง€๊ณ , ๋กœ์ปฌ ๋ช…๋ นํ–‰ ๋„๊ตฌ๋กœ๋„ ์›๊ฒฉ ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰์ค‘์ธ ๋„์ปค ์—”์ง„ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

15.1 ๋„์ปค API์˜ ์—”๋“œํฌ์ธํŠธ ํ˜•ํƒœ

  • ๋„์ปค ์—”์ง„์„ ์›๊ฒฉ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ ค๋ฉด ๋ช…์‹œ์ ์œผ๋กœ ์™ธ๋ถ€ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • HTTP ๋กœ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ฐ˜๋“œ์‹œ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.
  • ๋„์ปค ์—”์ง„์ด HTTP๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์„ค์ •๋  ๊ฒฝ์šฐ ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ๋งŒ ์•Œ๋ฉด ๋ˆ„๊ตฌ๋“ ์ง€ ๋„์ปค ์—”์ง„์„ ๋งˆ์Œ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

15.2 ๋ณด์•ˆ ์›๊ฒฉ ์ ‘๊ทผ์„ ์œ„ํ•œ ๋„์ปค ์—”์ง„ ์„ค์ •

๋„์ปค์—๋Š” API ์š”์ฒญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ฑ„๋„์ด ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

A. ์ „์†ก ๊ณ„์ธต ๋ณด์•ˆ (TLS)

  • ๋„์ปค API ๋Š” ์ƒํ˜ธ TLS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ๊ฐ ์ธ์ฆ์„œ๋ฅผ ๊ฐ€์ง„๋‹ค.
  • ์„œ๋ฒ„์˜ ์ธ์ฆ์„œ๋Š” ์ž์‹ ์„ ์ฆ๋ช…ํ•˜๊ณ  ์ „์†ก์„ ์•”ํ˜ธํ™” ํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๋Š” ์ž์‹ ์„ ์ฆ๋ช…ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.
  • TLS ๋Š” ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, ์ธ์ฆ์„œ ์ƒ์„ฑ, ๊ต์ฒด ๋“ฑ์˜ ๊ด€๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

B. ๋ณด์•ˆ ์…ธ (SSH)

  • SSH ๋Š” ๋ฆฌ๋ˆ…์Šค ์„œ๋ฒ„์—์„œ ์›๊ฒฉ ์ ‘์†ํ•˜๋Š” ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์ด๋‹ค.
  • SSH ๋Š” ํด๋ผ์ด์–ธํŠธ์— ๋Œ€ํ•œ ์›๊ฒฉ ์ ‘๊ทผ ๊ถŒํ•œ๊ด€๋ฆฌ๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฝ๋‹ค.

์ƒํ˜ธ TLS๋ฅผ ์ด์šฉํ•ด ๋„์ปค ์—”์ง„์˜ ๋ณด์•ˆ ์›๊ฒฉ ์ ‘๊ทผ ์„ค์ •ํ•˜๊ธฐ

A. ์ธ์ฆ์„œ์™€ ํ‚ค ํŒŒ์ผ ์Œ์„ ๋‘๊ฐœ ๋งŒ๋“ ๋‹ค.

B. ์ธ์ฆ์„œ๋ฅผ ๋ฐฐํฌํ•  ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

C. ๋‘ ๊ฐœ์˜ ๋ณผ๋ฅจ์ด ๋งˆ์šดํŠธ ๋œ๋‹ค.

D .์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋˜ ์ธ์ฆ์„œ์™€ daemon.json ํŒŒ์ผ์„ ๋…ธ๋“œ๋กœ ๋ณต์‚ฌํ•œ๋‹ค.

$ mkdir diamol-certs

# ca key ์Œ ์ƒ์„ฑ
$ openssl genrsa -out ca.key 2048

$ openssl req -x509 -new -nodes -key ca.key -days 365 -out ca.crt

# ์ธ์ฆ์„œ ์ƒ์„ฑ
$ openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr
$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -day 365

$ docker container run -v /diamol-certs:/certs -v /etc/docker:/docker diamol/pwd-tls:server

$ vi /etc/docker/daemon.json

{
  "hosts": ["unix://var/run/docker.sock", "tcp://0.0.0.0:2376"],
  "tls": true,
  "tlscacert": "/diamol-certs/ca.pem",
  "tlskey": "/diamol-certs/server-key.pem",
  "tlscert": "/diamol-certs/server-cert.pem"
}

$ sudo systemctl restart docker

๋ณด์•ˆ ์…ธ (SSH)

  • SSH ์˜ ์žฅ์ ์€ ๋„์ปค CLI๊ฐ€ ํ‘œ์ค€ SSH ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„์ปค ์—”์ง„ ์ชฝ์—์„œ ์„ค์ •์„ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ์‚ฌ์šฉ์ž ์ธ์ฆ์€ ์„œ๋ฒ„๊ฐ€ ๋Œ€์‹  ์ฒ˜๋ฆฌ, ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ํ˜ธ์ŠคํŠธ์—์„œ ์›๊ฒฉ ์ ‘์†์— ์‚ฌ์šฉํ•  ๊ณ„์ •์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋.

15.3 ๋„์ปค ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•ด ์›๊ฒฉ ์—”์ง„์—์„œ ์ž‘์—…ํ•˜๊ธฐ

  • ๋„์ปค ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์›๊ฒฉ์œผ๋กœ ์ ‘๊ทผํ•  ๋„์ปค ์—”์ง„์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋„์ปค ์ปจํ…์ŠคํŠธ๋Š” ๋„์ปค CLI ์—์„œ ์›๊ฒฉ ์ ‘๊ทผ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์ƒ์„ธ ์ •๋ณด๋ฅผ ์ง€์ •ํ•˜๋ฉด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
$ docker context create pwd-tls --docker "host=tcp://$pwdDomain, ca=/tmp/pwd-certs/ca.pem, cert=/tmp/pwd-certs/client-cert.pem, key=/tmp/pwd-certs/client-key.pem"

$ docker context create local-tls --docker "host=ssh://user@server"

$ docker context ls

$ docker context use pwd-tls
  • ์ปจํ…์ŠคํŠธ์—๋Š” ์›๊ฒฉ Docker ์—”์ง„ ๊ฐ„์— ๋Œ€์ƒ์„ ์ „ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด (์—”๋“œํฌ์ธํŠธ, ์ธ์ฆ์„œ ๋“ฑ)์ด ํฌํ•จ๋œ๋‹ค.
  • ์ปจํ…์ŠคํŠธ๋Š” ํ•œ ๋ฒˆ ์ƒ์„ฑ๋˜๋ฉด ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅ๋˜๋ฉฐ, ์ƒˆ๋กœ์šด ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜, ํŠน์ • ์ปจํ…์ŠคํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•œ ์ƒํƒœ๋Š” ํ„ฐ๋ฏธ๋„ ์„ธ์…˜๋งˆ๋‹ค ๊ฐœ๋ณ„์ ์ด๋‹ค.
  • ๋งŒ์•ฝ, ํ•ด๋‹น ์„ค์ •์„ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์—๋„ ๋ชจ๋‘ ์˜๊ตฌ์ ์œผ๋กœ ์„ค์ •ํ•˜๊ณ ์‹ถ์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.
$ export DOCKER_CONTEXT='pwd-tls'

15.4 ์ง€์†์  ํ†ตํ•ฉ ํŒŒ์ดํ”„๋ผ์ธ์— ์ง€์†์  ๋ฐฐํฌ ์ถ”๊ฐ€ํ•˜๊ธฐ

  • ์ธ์ฆ ์ˆ˜๋‹จ์€ ์ ˆ๋Œ€๋กœ ํ˜•์ƒ ๊ด€๋ฆฌ ๋„๊ตฌ์— ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ž๋™ํ™” ์„œ๋ฒ„๋Š” ๋น„๋ฐ€๊ฐ’์„ ๋นŒ๋“œ ์„œ๋ฒ„ ๋‚ด๋ถ€์— ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•˜๊ณ , ํŒŒ์ดํ”„๋ผ์ธ ์ž‘์—…์— ํ™œ์šฉํ•œ๋‹ค.
  • CI/CD ํŒŒ์ดํ”„๋ผ์ธ์€ Docker ๋ฐ Docker Compose ๋ช…๋ น์–ด๋ฅผ ์—ญํ• ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•ด ๋ณต์žก์„ฑ์„ ์ค„์ด๊ณ  ํšจ์œจ์„ฑ์„ ๋†’์—ฌ์•ผ ํ•œ๋‹ค.
$ vi Jenkinsfile

pipeline {
    agent any
    environment {
       REGISTRY = "registry.local:5000"
       UAT_ENGINE = "ip172-18-0-69-bthrciiosm4g00b8b730-2376.direct.labs.play-with-docker.com:80"
       PROD_ENGINE = "ip172-18-0-69-bthrciiosm4g00b8b730-2376.direct.labs.play-with-docker.com:80"
    }
    stages {
        stage('Verify') {
            steps {
                dir('ch15/exercises') {
                    sh 'chmod +x ./ci/00-verify.bat'
                    sh './ci/00-verify.bat'
                }
            }
        }
        stage('Build') {
            steps {
                dir('ch15/exercises') {
                    sh 'chmod +x ./ci/01-build.bat'
                    sh './ci/01-build.bat'
                }
            }
        }
        stage('Test') {
            steps {
                dir('ch15/exercises') {
                    sh 'chmod +x ./ci/02-test.bat'
                    sh './ci/02-test.bat'
                }
            }
        }
        stage('Push') {
            steps {
                dir('ch15/exercises') {
                    sh 'chmod +x ./ci/03-push.bat'
                    sh './ci/03-push.bat'
                    echo "Pushed web to <http://$REGISTRY/v2/diamol/ch15-timecheck/tags/list>"
                }
            }
        }
        stage('UAT') {
            steps {
                withCredentials([file(credentialsId: 'docker-ca.pem', variable: 'ca'),
                                 file(credentialsId: 'docker-cert.pem', variable: 'cert'),
                                 file(credentialsId: 'docker-key.pem', variable: 'key')]) {                    
                    dir('ch15/exercises') {
                        sh 'chmod +x ./ci/04-uat.bat'
                        sh './ci/04-uat.bat'
                        echo "Deployed to UAT"
                    }
                }
            }
        }
        stage('Await approval') {
            steps {
                input message: 'Deploy to prod?', ok: 'Do it!'
            }
        }
        stage('Production') {
            steps {
                withCredentials([file(credentialsId: 'docker-ca.pem', variable: 'ca'),
                                 file(credentialsId: 'docker-cert.pem', variable: 'cert'),
                                 file(credentialsId: 'docker-key.pem', variable: 'key')]) {                    
                    dir('ch15/exercises') {
                        sh 'chmod +x ./ci/05-deploy.bat'
                        sh './ci/05-deploy.bat'
                        echo "Deployed to PROD"
                    }
                }
            }
        }
    }
}

$ vi ./ci/00-verify.bat

docker version && docker-compose version

$ vi ./ci/01-build.bat

docker-compose -f docker-compose.yml -f docker-compose-build.yml build --pull

$ vi ./ci/02-test.bat

docker-compose up -d && docker-compose ps && docker-compose down

$ vi ./ci/03-push.bat

docker-compose -f docker-compose.yml -f docker-compose-build.yml push

$ vi ./ci/04-uat.bat

docker-compose --host tcp://$UAT_ENGINE --tlsverify --tlscacert $ca --tlscert $cert --tlskey $key -p timecheck-uat -f docker-compose.yml -f docker-compose-uat.yml up -d

$ vi ./ci/05-deploy.bat

docker-compose --host tcp://$PROD_ENGINE --tlsverify --tlscacert $ca --tlscert $cert --tlskey $key -p timecheck-prod -f docker-compose.yml -f docker-compose-prod.yml up -d

A. ๊ฒ€์ฆ ๋‹จ๊ณ„

B. ๋นŒ๋“œ ๋‹จ๊ณ„

C. ํ…Œ์ŠคํŠธ ๋‹จ๊ณ„

D. ์›๊ฒฉ ๋„์ปค ๊ฐœ๋ฐœ๊ธฐ ๋ฐฐํฌ

F. ์›๊ฒฉ ๋„์ปค ์šด์˜๊ธฐ ๋ฐฐํฌ

15.5 ๋„์ปค ๋ฆฌ์†Œ์Šค์˜ ์ ‘๊ทผ ๋ชจ๋ธ

๋„์ปค ์—”์ง„์˜ ๋ณด์•ˆ์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  • ๋ช…๋ นํ–‰ ๋„๊ตฌ์™€ API ์‚ฌ์ด์˜ ํ†ต์‹ ์„ ์•”ํ˜ธํ™”
  • ํ—ˆ๊ฐ€๋ฐ›์€ ์‚ฌ์šฉ์ž๋งŒ API ์ ‘๊ทผ ํ—ˆ์šฉ

๊ถŒํ•œ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์€ ์—†๋‹ค.

๋ชจ๋“ ๊ฒƒ์„ ํ• ์ˆ˜ ์žˆ๊ฑฐ๋‚˜, ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜์—†๋Š” ๊ฒƒ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋‹ค.

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—๋Š” ์—ญํ•  ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ์ œ์–ด ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ ‘๊ทผ, ๋ฆฌ์†Œ์Šค ์ œ์–ด ๋“ฑ์„ ์„ธ์„ธํžˆ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ๋‹ค.

728x90
๋ฐ˜์‘ํ˜•
MyeongDev