수업 67일차

galoo·2023년 10월 9일
0

HelloVision Dx Data School

목록 보기
61/72

✔ Docker

Dockerfile

여러 프레임워크의 Dockerfile 작성

  • Spring Boot Framewor 프로젝트의 Dockerfile 생성해서 구동해보기
    - Spring Boot를 사용하기 위해서는 jdk와 boot project 생성을 도와주는 ID(Eclipse-STS나 기업 또는 전자 정부에서 제공하는 IDE, IntelliJ의 Ultimate 버전 등)가 준비되어 있으면 됩니다.
    - Java는 Gradle이나 Maven이라고 하는 빌드 도구가 있기에, 이 도구를 이용해서 프로젝트를 빌드하기 때문에 python 처럼 의존성 라이브러리를 별도로 내보내서 설치할 필요가 없다.(requirements)
  • 환경 설정
    - JDK 설치
    - IntelliJ 설치(IDE)
    - Docker Engine 설치
    - 프로젝트 생성 :spring boot application (spring initializer), web 의존성만 체크
    - 코드 실행 뒤 확인 (브라우저 or curl 명령으로 확인)
    - 프로젝트 루트 디렉에 Dockerfile을 생성해서 작성
    - 기본이 Dockerfile이고, 다른 디렉에 존재하거나 이름이 다르면 빌드할 때, -f 옵션을 이용해서 경로를 직접,
    프로젝트를 clean build : 터미널 창에서 명령어를 입력
    - ./gradle clean build
FROM amazoncorretto:17
CMD["./mvnw","clean", "package"]
ARG JAR_FILE=target/*.jar
COPY ./build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
  • 이미지 생성
    - docker build -f Dockerfile -t docker-example:0.0.1 .
  • 이미지 확인
    - docker images 혹은 desktop 열어서 확인
  • 컨테이너 생성
    - docker run -p 8080:8080 -dit mino1998/docker-example:0.0.1 --name=springapp
  • 컨테이너구동 여부를 확인
    - docker ps
  • 브라우저에서 확인 (로컬호스트 8080)
  • DockerImage를 이용해서 클라우드에 직접 배포
    - 이미지를 직접 업로드 해도 되지만, docker hub에 업로드해서 경로를 설정해도 됩니다.
    - docker login 확인
    - docker push mino1998/example:0.0.1
  • Node Project를 Dockerfile 파일을 이요해서 구동
    - node를 학습하고자 하는 경우는 되도록이면 nextjs를 하는 것이 좋습니다.
  • 환경 설정
    - nodejs 설치(windows : http://nodejs.org 다운), node -v
    - 프로젝트 생성 : 빈 디렉에서 npm init
    - 웹을 위한 패키지 설치 : npm install express
    - pakage.json에 의존성 설명되어있음
    - app.js 하나 만들고 나서 (npm init 한 디렉에 넣기)
    - 실행 : package.json 의 Scripts 부분을 수정

    - npm start로 터미널에서 해보기

    - 앱이 실행중이다.
    - 도커 파일을 생성하고 컨테이너 생성하고 푸쉬까지 해보자.
    - 이미지 빌드 : docker build -t 이미지이름 [-f 도커파일 경로] .
    - 컨테이너 실행 : docker run -dit -p 3000:3000 --name=nodeapp nodeapp
    - 브라우저나 curl 명령으로 학인하기
    - 이미지 배포해보자 :

압축 파일 사용

  • Linux는 tar나 gz 확장자에 대해서는 압축을 해제하지 않고 사용 가능함
  • Linux에서는 tar나 gz는 압축을 해제할 필요가 없습니다.
  • web 압축 파일 다운로드
    - git clone https://github.com/brayanlee/webapp.git
  • dockerfiles 디렉에 Dockerfile 생성하고 작성
    - apache2 웹 서버 실행용
  • 이미지 생성
    - docker build -t webapp:1.0 . 으로 했었는데 이럼 빌드 안될거임
    - Dockerfile을 못찾는거임 (디렉이 다른가..?)
    - docker build -t webapp:1.0 -f ./dockerfiles/Dockerfile .
    - 경로를 설정 잘 해주자!
  • 컨테이너 생성
    - docker run -dit -p 8001:80 --name=webapp webapp:1.0
  • html, css, js만으로 구성된 웹 플젝이 있는 경우, 디렉을 그대로 가져와도 되지만, 압축된 형태를 이용해도 됩니다., 굳이 압축을 풀어서 쓸 필요는 없다.

이미지 용량 절감

ubuntu 이미지의 경우

  • 이미지를 절감할 수 있는 명령
    - apt-get clean -y혹은 apt-get autoclean -y
    - 설치에 사용한 패키지 라이브러리, 임시 파일 또는 오래된 파일을 삭제
    - apt-get autoremove -y
    - 다른 패키지들의 종속성을 충족시키기 위해 설치한 패키지를 삭제
    - rm -rfv /var/lib/apt/lists/* /tmp/* /var/tmp/*
    - 캐싱된 파일을 모두 삭제(리눅스나 도커는 이전에 설치한 파일의 캐시를 가지고 있다가 다시 설치하는 경우에는 빠르게 설치하거나 빌드를 함

다단계 빌드

  • go 나 c의 애플리케이션을 이미지로 만드는 경우, go 나 c는 바로 실행 파일을 만들지 않고, 목적 프로그램을 먼저 생성한 뒤에 실행파일을 만들어서 실행하는데, 프로그램을 실행만 하는 경우에는 중간에 만든 목적 프로그램은 필요가 없는데, 이미지로 바로 만들면, 목적 프로그램도 이미지에 포함되어서 이미지의 용량이 커지게 된다.
  • 이런 경우에는 최종으로 생성된 파일만 이미지에 포함되도록 해주어야 합니다.

go를 이용한 다단계 빌드

  • 설치
    - https://go.dev/dl/ 에서 다운로드 받아 설치 (MAC은 환경 변수 설정 필요)
    - go version 으로 버전 확인
  • go를 만든 목적은?
    - google의 운영체제 커널을 개발하는 것이었는데, os kernel을 만드는 프로젝트는 더 진행 안하고 클라우드의 핵심이 되는 애플리케이션 개발에 go를 주로 사용함(kubernetes, docker)
  • 다른 언어와 go의 차이점은?
    - 별도의 라이브러리라 거의 없지..
    - 오픈소스와는 잘 되어있지만, 오픈소스가 아닌 것과는 호환이 약간 좀 그렇다.
  • 다단계 빌드를 위한 디렉토리 생성
    - 이미지 빌드를 할 때는, 디렉의 모든 내용을 읽어서 수행하기 때문이다.
    - 불필요한 파일이 있다면, 메모리를 잡아먹는다.
  • 디렉에 main.go 쓰기(vscode 쓰면 편함)
  • 실행(2가지 과정)
    - go build 소스파일경로을 이용하면 실행 프로그램이 생성됨
    - 이후 cmd에서 소스파일.exe 해버리면 실행된다. (windows기준)
  • 다른 플랫폼을 위해서 빌드를 할 때는
    - GOOS=운영체제 GOARCH=칩셋 go build 소스파일경로 해주면 됩니다.
    - os linux 등.. GOARCH에서는 칩셋을 써주면 됩니다.
    - GOOS=linux GOARCH=amd64 go build main.go 이렇게 하면 됩니다.
  • 실행파일 이름 변경을 원한다면(바이너리 파일 이름 변경)
    - go build main.go -o app.exe 이렇게 하면 됩니다.
    - Dockerfile에는 GOOS= GOARCH= 를 써주어야 합니다.(DOCKER는 linux에서 동작하기 때문)
  • 도커파일을 만들자
  • 이미지를 만들자
    - docker build -t goapp:1.0 .
  • C나 GO는 binary 파일을 만들기 때문에, C나 Go Compiler가 필요가 없어요!
    - 다단계 빌드를 이용해서 마지막 실행 파일만 가지고 이미지를 만들면 용량이 확 줄어듭니다.
    - python, node, java는 줄 단위로 번역하면서 실행되던가 jvm 위에서 실행되기에 항상 실행을 하기 위해서는 무엇인가가 더 필요합니다.
    - 클라우드 환경에서는 실행되는 프로그램의 크기가 크다면 그만큼 비용이 더 커지게 됩니다.
  • 이미지를 빌드하자
    - docker build -t goapp:1.0 .
  • 컨테이너 생성
    - docker run --name goapp goapp:1.0

yaml(yml)파일 작성법

기본 문법

  • 들여쓰기
    - 2칸이나 4칸
  • map
    - json 은 {"api" : "v1"} 이러는데, yaml은
map
	apiVersion: v1
	kind: Pod
array
	skills:
    	- docker
       	- kubernetes
주석
	#comment
  • 숫자는 따옴표 없이 표기
  • 문자열은 큰 따옴표 안에 표기
  • boolean은 true/false, yes/no(대소문자 구분 안함) 가능함
  • 줄바꿈은 |(마지막에도 줄 바꿈이 적용)
  • |- 은 마지막 줄 바꿈이 적용 안됨
  • > 은 빈 줄을 제외
  • key와 value를 작성할 때, value 앞은 빈칸이 필요하다.
  • value가 문자열인 경우, 대부분 따옴표 없이 작성해도 괜찮지만, ;이 포함된 경우에는 반드시 따옴표를 해야 합니다.
  • windows_drive: C
  • windows_drive: "C"
  • windows_drive: c: => 이 경우에는 에러

  • 대부분의 경우, yaml은 json으로 번역되어서 수행
  • json으로 작성한 뒤, yaml로 변경하거나 yaml로 작성한 뒤 json으로 변경 (https://www.json2yaml.com/)
  • yaml이 사람들이 더 보기 쉬워서(알아보기 쉬워서) 바꿔나가는 것이다. json으로 변경때려서 하긴 함

✔ git hub action을 이용한 docker hub 배포

  • 실행 가능한 application 생성
    - main.go
  • 빌드
    - go build main.go
  • 실행
    - main.exe
  • Dockerfile 만들어서 이미지로 만들어지는지 확인하기
    - 빌드 : docker build -t goapp:1.0 .
  • 컨테이너 생성하기
    - docker run --name goapp-deploy goapp:1.0
  • 현재 프로젝트를 git hub에 업로드
    - git hub에 repo 생성
   	- git init
   	- git add .
   	- git config --global user.name 유저이름
   	- git config --global user.email 이메일
   	- git commit -m "메시지"
   	- git remote add origin(이름) 레포주소
   	- git push origin main(브랜치) 
    	-> 이거 실패하면 git checkout -b main 수행
  • github에서 dockerhub에 로그인하기 위해 dockerhub에서 access token발급 받자
    - hub.docker.com 에서 account settings로 들어가자
    - security -> access Token에서 New 해서 만들자
    - 발급 완료!
  • 업로드에 사용할 repo를 생성해야 합니다. (docker hub)
  • git hub에서 repo의 action 카테고리에 들어가자
  • 3번째 친구로 선택해보자.(publish docker container)

Git Action 만들기

  • git hub repository에서 action을 누르고 새로운 workflow를 생섷애서 작업
name: GitAction
# on은 어떤 이벤트가 발생했을 때, 
# cron이면 주기적인 작업이 되는 것이고, 
on:
  push:
    branches: ["main"] # 메인 브랜치에 push 이벤트가 발생하면
  pull_request:
    branches: ["main"] # 메인 브랜치에 pr이 발생하면
#뭘 할 것인지 작성하자
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set Up GO
        uses: actions/setup-go@v3
        with:
          go-version: 1.15
      - name: Build
        run: go build -v ./... #현 디렉에 있는 모든 것을 build
      - name: Login To DockerHub
        uses: docker/login-action@v1
        with: 
          username: mino1998
          password: 도커허브에서 발급받은 access token
      - name: build and release to DockerHub
        env: 
          NAME: mino1998
          REPO: gitaction
        run: |
          docker build -t $REPO .
          docker tag $REPO:latest $NAME/$REPO:latest
          docker push $NAME/$REPO:latest
  • 이걸 커밋해버리면 local에선 이젠 push 불가능이다.
    - 왜냐하면 commit point가 달라졌기 때문이다.
    - pull을 먼저 해줘야 한다.
    - git pull origin main
  • main.go 를 수정하고 git을 push 하자
    - 내용을 바꾸고 add commit push만 해보자.
  • 실패 버전
  • 작업중.... 이게 CD 이다.
  • 성공
  • 그러고 이제 cmd에서 docker run mino1998/gitaction를 해보자. 그러면 바뀐 것이 바로 뜰 것이다.
    - 즉, 내가 바뀐것을 직접 수정한걸 업로드하지 않아도 이제 git push 까지만 하면 자동으로 배포되는 것을 확인할 수 있다.
    - 소스 코드를 수정하고, git hub의 소스 트리에 push나 pull request를 git action에 설정된 내용이 수행됩니다.
  • 도커 허브에 업로드
  • 가장 많이 수행하는 작업이 도커 허브에 업로드 하거나, jenkins를 이용한 build나 public cloud에 전송하는 작업이다.

git hub action을 이용한 docker hub 배포

  • 동작하는 application과 Dockerfile 작성
    - main.go 파일 만들고 실행해보자.
    - go build main.go, main.exe 물론 해당 디렉에서 해야한다.
  • 동작하는 application과 Dockerfile을 github에 업로드
FROM golang:1.13-alpine as builder
# git 설치 안되어있을까봐 불안해서 한번 해보자.
RUN apk update && apk add git  
WORKDIR /usr/src/app
COPY . . 
# COPY main.go . 라고 써도 상관없다.
# 디렉 안의 go 파일들을 빌드해서 main이라는 바이너리 파일을 현재 디렉에 생성해라
RUN CGO_ENABLED=0 GOO=linux GOARCH=amd64 go build -o main .
# 다단계 빌드 때문에 작성
FROM scratch 
# 앞의 builder라는 from 절에서 /usr/src/app 디렉의 내용을 현재 디렉으로 복사
COPY --from=builder /usr/src/app . 
CMD ["/main"]

  • 이미지 로 생성해서 잘 되는지 확인하자
    - docker build -t 이미지이름 .
    - docker run --name goapplication goapplication(이미지이름임)
    - 계속 동작하는 것이면 -dit, 외부 접근 하면 -p 포트번호:포트번호
  • docker hub에서 access token을 발급받고, repository를 생성
  • git hub에서 git action을 생성(로컬 프로젝트의 .github 디렉토리의 workflows 디렉토리에 yaml파일로 만들어서 업로드 해도 됩니다.)
    - git action을 만들어서 commit 하기만 해도 docker hub repo에 이미지 하나가 만들어진다.
  • 이제 소스코드를 고치고(pull and update) push를 해보자.
  • git action이 진행된 것을 확인할 수 있다.
  • 이후 docker run repo/이름:tag 를 cmd에서 해보자.
  • 변경된 부분이 잘 나온 것을 확인할 수 있다.

✔ Docker-Compose

개요

  • 시스템 구축과 관련된 명령어를 하나의 텍스트 파일에 기재해서 한 번에 시스템 전체를 실행하고 종료와 폐기까지 한번에 하도록 도와주는 도구
  • 공통의 목적을 갖는 애플리케이션 스택을 docker compose yaml 코드로 작성하고, 한 번에 서비스를 올리고 관리할 수 있는 도구

  • 데이터베이스는 mysql을 사용하고, 클라이언트의 요청은 node.js를 이용해서 처리하고 클라이언트 애플리케이션은 react로 배포하고자 하는 경우
  • 하나의 network로 묶어서 배포하는 방식
    - 권장하지 않음
  • 별개의 컨테이너로 배포한 뒤, 네트워크로 연결하거나 포트포워딩을 이용해서 접근
  • 별개의 컨테이너로 배포한 뒤, 네트워크로 연결하거나 포트포워딩을 이용해서 접근
    - 하나의 정의 파일을 이용해서 배포한다면
    - 그것이 docker-compose 이다.

  • yaml 포맷으로 기술된 설정 파일을 이용해서 여러 container 간의 실행이나 관계를 설정한 뒤, 일괄 실행 또는 일괄 종표 및 삭제할 수 있는 도구
  • 도커 명령어와 유사하지만, 도커 명령어는 아니다.

docker-compose와 Dockerfile의 차이

  • Dockerfile은 하나의 이미지를 만들기 위한 것으로, 네트워크나 볼륨의 생성은 못함
  • docker-compose는 docker run 명령을 여러 개 모아놓은 것과 같다.
    - 컨테이너 주변 환경을 생성하고 네트워크와 볼륨을 함께 만들 수 있다.
  • kubernetes를 학습한 경우, 대부분 docker-compose보단 kubernetes를 이용

설치

  • MAC, Windows에서 Docker Desktop 사용하는 경우에는 별도의 설치가 필요 없음
  • Linux에서는 별도로 설치를 해야 함

샘플

  • apache web server(httpd)를 만들어서 실행하는 일을 하고 싶다.
  • docker run --name apa000 -d -p 8080:80 httpd 이렇게 명령어 치면 됨
    - 이게 되긴 하는데, 해당 명령을 자주, 매번 입력하는 것은 자원의 낭비임
    - docker-compose.yaml 파일을 작성하는 것은 어떨까?
version: "3"
services: 
  apa001: # 컨테이너 이름
    image: httpd # 이미지
    ports: # 포트포워딩
      - 8081:80 # 8081포트 사용
    restart: always
  • docker-compose up을 해보자.
    - docker ps로 컨테이너 생성 확인

maria db 컨테이너 생성 예시로 생각해보자.

  • 명령어
    - docker run --name mariadb -d -p 3306:3306 --restart=always -e MYSQL_ROOT_PASSWORD=root mariadb
  • docker-compose 이용
version: "3"
services:
  maridadb:
    image: mariadb:10.4.6
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - 3306:3306
    restart: always
  • 이건 여러번 반복할 때 docker-compose가 좋겠지

작성 방법

  • 주 항목
    services: 컨테이너
    networks: 네트워크
    volumes: 볼륨
  • 정의 내용
    image
    networks: --net
    volumes: -v
    ports: -p
    envirionment: -e
    depends_on: 다른 서비스에 대한 의존 관계, 다른 서비스를 먼저 실행시킬 때 사용(ex: wordpress하려면 mysql이나 mariadb가 먼저 나와야 하기에 depends_on에 mysql이나 mariadb 설정하기)
    restart: 컨테이너 종료시 재시작 여부(no, always, on-failure, unless-stopped), 은근 쓰는게 always이다.
  • 버전 정의
    - yaml 코드의 첫 줄은 버전을 명시
    - 이 버전에 따라 지원하는 도커 엔진의 버전이 달라지게 됩니다.
    - 3.9라고 설정하면 도커는 19.03 버전 이상이어야 합니다.
    - 3이라고 하면 거의 모든 도커 버전을 지원
    - 버전을 확인하면서 작성하는 것을 권장하는데, 그 이유는 docker와 kuberentes는 업데이트 속도가 굉장히 빠르기 때문이다.
profile
밀가루 귀여워요

0개의 댓글