Hi yoahn 개발블로그

오픈소스 소프트웨어 중간 정리 본문

sswu

오픈소스 소프트웨어 중간 정리

hi._.0seon 2022. 3. 20. 14:17
반응형

1. 오픈소스 SW

1.1 Open-Source Software

소스 코드를 공개해 누구나 특별한 제한 없이 그 코드를 보고 사용할 수 있는 오픈 소스 라이선스를 만족하는 소프트웨어

 

Free -> 제한 없음, 자유로운 사용

- 무료가 아님

- 사용, 수정, 재배포로부터 자유로움

- 어떤 목적으로도 라이센스를 준수하는 한 자유로운 사용

 

1.2 오픈소스의 양방향 프로세스

  • 오픈소스 사용하기
  • 오픈소스 기여하기
  • 오픈소스 공개하기

1) 오픈소스 사용하기

  • 소프트웨어는 저작권, 특허권, 상표권, 영업비밀 등으로 보호됨
    - 소프트웨어는 개발과 동시에 자동으로 독점 권리를 보호
  • 오픈소스 소프트웨어는 개발자와 사용자 간의 사용 방법 및 조건의 범위를 명시한 라이선스로 권리 보호
    - 소스코드를 개방했을 뿐, 지식재산권으로 보호되는 저작물

2) 저작권과 라이선스

  • 라이선스
    • 라이선서 (라이선스 소유자)로부터 라이선스를 사용하려는 라이선시(제3자)에게 지적재산권을 이전하는 계약
  • 사유 소프트웨어 VS 오픈소스 소프트웨어 라이선스
    • 권리자가 사용자에게 라이선스를 부여하고 사용자는 그 대가를 지급
    • 로열티 요구 대신 지켜야 할 의무사항 요구

1.3 소프트웨어 라이선스 분류

FOSS 라이선스 (Free Open Source SW)

  • 반환 의무
    • 오픈소스를 사용하여 소프트웨어를 만든 경우 그 프로그램의 소스코드까지 공개해야 함
  • 반환 불필요
    • 오픈소스를 사용하여 소프트웨어를 만들었어도 프로그램 소스코드 공개할 필요 없음
    • 오픈소스를 사용하여 만든 소프트웨어로 운영하더라도 상관없음

  • 상용SW
    • 실행파일만 제공
    • 리버스엔지니어링 금지
    • 바이너리도 복제, 배포, 수정 불가
    • 사용기간에 제한 있음
    • EULA : End User License Agreement
  • 공개 SW
    • 소스코드 제공
    • 소스코드 사용, 복제, 수정, 재배포 허용
    • 사용기간 무제한

소프트웨어 라이선스

구분 무료 라이선스 유료 라이선스
-> 기술 지원이 포함됨
소스코드 공개 대부분 OSS
(Apache, Tomcat, ..)
일부 배포판 OSS
(Red Hat, MySQL)
소스코드 비공개 Freeware(Winzip),
Shareware(초기에만 무료)
Adware(광고가 붙은 SW, JetAudio)
상용 비공개 소프트웨어
(MS Office, Oracle, ..)

1.4 오픈소스 라이선스 분류

  • Permissive (관대한)
    • 재배포를 한다고 해서 프로그램 코드를 공개할 필요 없음
    • 상용 소프트웨어를 만드는 회사에서 선호함
    • 사용자 친화적
    • MIT License, BSD, Apache License,,,
  • Weak Copyleft
    • 수정없이 동적 라이브러리 형태로 동작할 경우엔 소스코드 공개할 필요 없음
    • MPL, EPL, LGPL
  • Strong Copyleft
    • 조금이라도 수정하거나 정적/동적으로 참조하여 사용하는 경우 프로그램 코드를 모두 공개해야 함
    • 원저작자 친화적
    • GPL, AGPL,,

1) 오픈소스 라이선스 의무사항 적용 범위

  • 오픈소스를 복제하거나 수정해서 사용하는 경우, 내부에서 사용하는 경우에는 상관 없음
  • 배포하는 경우, 무료 / 유료 배포와 상관없이 소스코드를 공개해야 한다.

2) 오픈소스 라이선스 주요 요구사항

  1. 저작권 고지 의무
    • 저작권법에 따른 법적 권리 보장
    • 공개 SW 라이선스 미 준수 시 저작자와 분쟁 가능
  2. 라이선스 사본 포함 (영문)
  3. 보증의 부인
  4. 책임의 제한
  5. 소스코드 반환
    • 특정 라이선스는 소스코드 반환의무를 가짐
    • AGPL, GPL, LGPL, MPL, EPL 등
    • 링크되거나 코드가 포함된 SW의 소스코드 공개의무가 발생
    • 비 공개 SW가 공개 SW로 변경될 수 있음
    • 특허, 영업비밀, 핵심기술 등의 외부 유출 가능성 존재
  6. 특허 조항

1.5 오픈소스 프로젝트의 구성원

  • 리더
    • 일반적으로 저작자가 역할을 담당
    • 프로젝트의 방향 결정
    • 의사결정이 필요할 때 최종 결정을 담당
    • 프로젝트의 규모가 클 경우, 운영 위원회를 조직하여 리더의 역할을 수행
      (Linus Torvalds)
  • 메인테이너
    • 프로젝트의 핵심 기여자
    • 가장 신뢰할 수 있는 기술 역량 보유
    • 리더로부터 특정 영역을 위임받아서 주도적으로 관리
    • 일정관리, 코드 리뷰 및 Merge여부 결정
  • 커미터
    • 프로젝트 내 특정 모듈의 코드를 충분히 이해하면서 정기적인 기여 활동을 하는 사람들
    • 컨트리뷰터의 기여를 Review 및 승인할 권한이 있음
    • 특정 모듈에 대해 메인테이너의 승인을 받지 않고도 Merge할 권한을 갖음
  • 컨트리뷰터
    • 누구라도 간단한 기여 사실이 있다면 컨트리뷰터
      - 간단한 버그 수정, 문서화 등도 포함
    • 기여는 수련된 커미터 및 메인테이너에 의해 리뷰 과정을 거치면서 보완이 된 후 저장소에 Merge됨
  • 사용자
    • 오픈소스 프로젝트에서 가장 중요한 역할
    • 프로젝트를 사용하면서 버그 리포트, 새로운 기능 제안 등 아이디어를 제공
    • 프로젝트의 리더, 메인테이너, 컨트리뷰터들이 사용자의 요청을 신중히 듣지 않으면 프로젝트가 장기적으로 성공하기 어려움

예시

  • User
    Inkscape를 처음 접한 사람
  • Seeker
    사용하면서 버그 발생 -> 해결 방법 찾기 -> 해결 방법 공유
  • Collaborator
    버그를 고치고 싶어 짐 -> 버그 트래커에서 다른 사람이 보고한 버그 리포트에 자신의 버그 발생 환경을 댓글로 남김
  • Contributors
    -> 코드 수정을 하는게 아니더라도 적극적으로 오픈소스 발전을 위해 노력하는 거 자체가 컨트리뷰터

1.6 오픈소스 기여하기

1) 컨트리뷰션의 유형

  • 문서 작성 / 번역 / 오타 수정
  • 테스트 / 이슈 생성
  • 디자인
  • 코드 작성 / 리뷰
  • 마케팅, 이벤트 행사

2) 오픈소스 기여의 혜택

  • 유지 관리 비용 절감
    • 오픈소스를 사용하면서 버그 수정 / 새로운 기능 추가
    • 오픈소스에 기여하지 않으면
      중요한 보안 패치 / 새로운 버전이 나왔을 때, 매번 변경사항을 반영한 후, 기능이 정상적으로 동작하는지, 성능에 영향이 없는지 매번 테스트 해야 함
    • 기여의 중요성에 대해 개발자 교육 필요
      (시간 없다고 안하면 장기적으로 더 많은 시간과 노력이 필요한 악순환 발생)
  • 오픈소스 프로젝트 방향에 영향을 미칠 수 있음
    • 오픈소스 프로젝트에서 기업에 꼭 필요한 기능을 추가해주길 바라면?
      기능을 제안하고, 직접 개발하고 기여하는 등 오픈소스 커뮤니티 내에서 활발히 활동할 필요가 있음
    • 기여한 후에는 커뮤니티의 여러 사람의 참여를 통해 해당 기능을 안정화하고 고도화하여 결과적으로 기업이 원하는 방향으로 성장
  • 우수한 개발자 고용
    • 우수한 오픈소스 개발자를 찾을 수 있는 가장 좋은 장소는 오픈소스 커뮤니티

3) 오픈소스 기여 방법

  1. 이전 이력 확인
    1. README.md, Issue, 메일링 리스트 등 확인
    2. CONTRIBUTING문서 확인하여 기여 방법 확인
  2. Issue 생성
    1. 스스로 해결할 수 없는 오류 보고
    2. 새로운 기능 또는 아이디어 제안
    3. 커뮤니티 비전, 또는 정책에 대한 토론
    4. 스스로 답을 알아낸 경우, Comment를 작성하고 Close
  3. Pull Request 생성
    1. 사소한 수정사항 제출
    2. Issue에서 이미 논의가 된 사항에 대해 작업
    3. 작업이 완료되기 전에 일찍 오픈하여 다른 사람들의 피드백 받음
    4. 커뮤니티의 컨벤션을 잘 따랐는지
  4. Feedback 받기
    1. 응답이 없는 경우
    2. 수정 요청을 받는 경우
    3. 거절되는 경우
    4. 수락

4) 오픈소스 공개의 혜택

  • 경제적 이득
    • 모든 참가자가 협력함으로써 자신들이 투자한 것보다 더 높은 수익을 얻을 수 있다.
    • 구글의 Android 오픈소스 공개
  • 표준이 될 수 있다
    • 해당 기술 분야의 사실상 표준이 되면 참여하는 외부 기여자가 많아지고, 프로젝트와 주변 생태계가 더 빠르게 진화
    • 산업 전반의 혁신을 가속화하고 프로젝트를 이용하여 구축한 서비스 및 제품의 채택을 용이하게 함
  • 생태계 성장
    • 다른 사람들이 오픈소스를 사용하여 자신의 프로그램을 개발 -> 프로젝트 성공을 위해 기여
  • 우수한 개발자 채용

2. Devops

2.1 전통적인 개발 운영 체계

  • 개발과 운영의 분리
    • 개발팀의 개발 완료 -> 테스트를 거쳐 운영 팀에 이관
    • 이관된 시스템은 개발팀이 관여하지 않고 운영팀에 의해 유지
  • 성격의 차이
    • 개발팀: 새로운 서비스의 신속하고 빠른 배포 중점
    • 운영팀: 안정성, 보안, 고가용성을 유지할 수 있는 서비스 유지가 목표
  • 전통적인 개발 운영 체계의 문제점
    • 장애발생 - 책임 모호
      • 개발자는 인프라 시스템에 대한 이해 부족
      • 운영팀은 애플리케이션에 대한 이해 부족
      • 책임 미루기로 인한 문제 해결 지연
    • 운영 이슈에 대한 처리
      • 개발은 운영으로 이관 후 서비스에 관심 갖지 않음
      • 운영은 계속해서 사용자와 상호작용하고, VOC(Voice of Customer)를 받음
      • 운영팀은 사용자의 의견을 들어서 서비스를 개선하고 싶어 개발팀에 서비스 개선 요청
        -> 개선 요청 사항은 개발팀 입장에서는 추가적인 일이 되어, 받지 않으려고 함
    • 빠르고 안정적인 배포의 어려움
      • 빠른 비즈니스 환경 변화에 따라가기 위해 많은 변경 요구
        -> 잦은 변경 배포
      • 제대로 된 테스트를 거치지 못한 경우 장애 발생 확률 Up
      • 운영팀은 잦은 배포를 꺼리고, 전통적인 방식의 주기적인 릴리즈와 테스트를 선호함

2.2 DevOps

  • 해결책 = DevOps
    • Development + Operation
    • 애플리케이션 개발 - 운영 간의 협업 프로세스를 자동화하는 것
    • 결과적으로 애플리케이션 개선 속도를 빠르게 함
    • 인프라에 대한 전문 지식이 없어도, 오픈소스와 클라우드의 도움을 받아 개발자도 "운영"을 겸업할 수 있게 됨

1) DevOps의 필수 요소

  • CALMS 모델
    • Culture (문화)
      • 변화를 받아들이는 문화
      • 협업하는 문화
      • 잘못을 따지기보다 결과 개선에 집중하는 문화
    • Automation (자동화)
      • Everything-as-code
      • 반복적인 수동 업무를 제거
      • CI/CD
    • Lean
      • 사용자에게 가치를 전달하는 일에 집중
      • 불필요한 일 제거
      • 지속적인 개선과 실패 인정(애자일)
    • Measurement (측정)
      • 지속적인 개선을 위한 노력의 결과를 성과지표로 측정
    • Sharing (공유)
      • 지식과 정보의 공유
      • 책임과 성공의 공유

2) CI/CD

  • 지속적인 통합
    • 개발자가 작업한 코드를 자동으로 테스트하고 테스트에 통과하면 코드를 통합하여 저장
  • 지속적인 배포
    • 작업한 코드 및 변경사항들은 테스트를 거쳐 레포지토리에 업로드되고 실제 서비스 배포까지 자동화
전통적인 방식 CI/CD
코드 수정에서 배포까지 많은 시간 소요 개발된 코드를 기존 코드에 Merge하기 전에 잘 작동하는 지, 규칙에 맞게 개발되었는지 자동으로 테스트
QA테스팅에서 많은 버그 발생 가능 테스트 통과한 코드를 바탕으로 빌드 후 테스트

3. GIT

버전관리

  • 공학과 소프트웨어 개발에서 팀 단위로 개발 중인 소스코드나 청사진 같은 설계도 등의 디지털 문서를 관리하는데 사용됨
    • 소스 관리 (Source Control)
    • 소스 코드 관리 (SCM, Source Code Management)

버전 관리의 필요성

  • 시스템 문제 발생시 복구 가능
  • 프로젝트 진행 중 과거 특정 시점으로 돌아가야 할 경우
  • 협업 시 각자가 수정한 부분을 동기화 하는 과정을 자동화
  • 소스코드의 변경 사항 추적
  • 소스코드 수정한 사람 추적
  • 대규모 수정 작업을 더욱 안전하게 진행
  • 코드의 특정 부분에 대한 수정사항 확인

3.1 버전 관리 시스템 (VCS)

  • 동일한 정보에 대한 여러 버전을 관리
    • 공동 프로젝트 관리, 프로젝트 백업, 데이터 동기화
    • 파일 변화를 시간에 따라 기록하여, 나중에 특정 시점의 버전을 다시 꺼내올 수 있는 시스템
      • 이전 상태 복구
      • 수정 내용 비교
      • 원인 추적
      • 언제 만든 이슈인지 확인
  • 종류
    • 로컬 버전 관리 시스템
      • 간단한 디비로 파일의 변경 정보 관리
      • 협업의 어려움
    • 중앙 집중식 버전 관리 시스템 (CVCS)
      • 파일 관리 서버가 별도로 존재. 클라이언트가 중앙 서버에서 파일을 받아서 사용
      • 중앙저장소에서 프로젝트 관리의 모든 것을 처리
      • 중앙 저장소 내에서 로컬 복사 후 변경한 사본을 커밋하는 방식으로 진행
      • 가장 최신의 복사본만 가짐
      • 문제점
        • Single Point Of Failure
        • 중앙 서버에서 문제 발생 시 서버가 다운된 동안 작업 불가능
        • 중앙 데이터베이스가 있는 저장장치에 문제가 생기면 프로젝트의 모든 히스토리를 잃을 수 있음
    • 분산 버전 관리 시스템 (DVCS)
      • 단순히 파일의 마지막 스냅샷이 아니라 모든 변경사항 목록이 저장
      • 저장소를 전부 복제
      • 모든 Check-Out 은 모든 데이터를 가진 진정한 백업
      • 서버에 문제가 생기면 어떤 클라이언트 중에 하나를 골라도 서버를 복원할 수 있음

중앙 집중식 버전 관리 시스템
분산 버전 관리 시스템

3.2 GIT

소스 코드 관리를 위한 분산 버전 관리 시스템

  • 라이선스: GNU GPL 2.0
  • 프로그래밍 언어: C, Shell, Perl, Tcl, Python
  • 특징
    1. 차이가 아니라 스냅샷
      • 기존 VCS -> 각 파일의 변화를 시간 순으로 관리, 기존에서 변경된 만큼만 저장함
        파일들의 집합을 관리
      • Git
        • 데이터를 파일 시스템 스냅샷으로 취급
        • 파일이 달라지지 않았으면, 파일을 새로 저장하지 않음
          (이전 상태의 파일에 대한 링크를 저장)
        • 데이터를 스냅샷의 스트림처럼 취급
    2. 거의 모든 명령을 로컬에서 실행
      • 원격 저장소와 로컬 저장소
      • 거의 모든 명령이 로컬 파일 & 데이터 사용
      • 프로젝트의 히스토리를 조회할 때 서버 없이 조회 가능. CVCS는 모든 명령에 네트워크 오버헤드 발생
      • 오프라인 상태에서도 작업 가능
        (오프라인에서 커밋은 가능함)
    3. Git의 무결성
      • 데이터를 저장하기 전에 항상 체크섬을 구하고, 그 체크섬으로 데이터를 관리
      • Git 모르게 파일이나 디렉토리 수정하는 것은 불가능
      • Git은 모든 것을 이 해시 값으로 식별
        (해당 파일의 해시 값으로 저장함)
    4. Git은 데이터 추가를 함
      • Git 으로 뭘 하든 데이터베이스에 추가됨
        • 시스템을 복구 불가능하게 만들기 어려움
        • 데이터를 완전히 삭제하는것도 어려움
      • Commit 을 하고 나면, 변경사항들을 잃어버리거나 망칠 것을 걱정할 필요 없음
        • 다른 Repository에 주기적으로 Push할 경우에는 더 필요 없음
      • Git의 세가지 상태
        1. Modified
          파일을 수정하기는 했지만, 아직 로컬 데이터베이스에 Commit하지 않은 상태
        2. Staged
          현재 수정한 파일이 다음 Commit 스냅샷에 포함될 거라고 표시한 상태
          변경사항들이 저장되는 곳 ( .git/index )
        3. Commited
          데이터가 로컬 데이터베이스에 안전하게 저장된것을 의미
      • Working Directory
        • 프로젝트에서 하나의 체크아웃 버전
        • .git/ 데이터베이스에서 압축 해제되어 사용하거나 수정할 수 있는 파일/디렉토리 형태로 재구성됨
      • Staging Area = Index
        • 다음 커밋에 어떠한 내용이 포함될 것인지를 저장하는 파일
        • .git/index 파일에 저장
      • .git/
        Git이 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 장소
      • Git 워크플로우
        1. Modified
          Working Tree에서 파일 수정
        2. Staged
          Staging Area에 파일을 Stage해서 커밋할 스냅샷을 만듦
        3. Commited
          Staging Area에 있는 파일들을 커밋해서 Git 디렉토리에 영구적인 스냅샷으로 저장

Git 파일 스냅샷 스트림
git의 세가지 상태

1) git 최초 설정

  • git config
    1. /etc/gitconfig
      1. 시스템모든 사용자와 모든 저장소에 적용되는 설정
      2. git config --system
        명령으로 이 파일을 읽고 쓸 수 있음
    2. ~/.gitconfig, ~/.config/git/config
      1. 특정 사용자에게만 적용되는 설정 (사용자 디렉토리에 설정)
      2. git config --global
        이 파일을 읽고 쓰는 명령
      3. git config --global user.name "John Doe"
        git config --global user.email johndoe@example.com
        git config --global core.editor vi
    3. .git/config
      1. 이 파일은 .git/ 디렉토리에 있고, 특정 저장소에만 적용됨 (현재 .git/ 폴더가 있는, 현재 작업중인 프로젝트)
      2. git config --local
        이 파일을 읽고 쓰는 명령
    4. 우선순위: 3 -> 2 -> 1
      1 -> 2-> 3 순서로 적용됨 (적용되면서 중복되는 설정은 덮어쓰임)
  • git config --list
    명령을 통해 설정한 내용 확인
  • git config <key>
    특정 key에 대해 어떤 값을 사용하는지 확인 가능
  • 도움말 보기
    • git help <verb>
    • git <verb> --help
    • man git-<verb>

2) Git 의 기초

  • git init
    • 기존 디렉토리를 Git 저장소로 만들기
    • .git/ 디렉토리가 생성됨
    • 아직 어떤 파일도 관리하지 않음 (어떤 파일도 트래킹 하지 않는 상태)
  • git clone
    • 기존 저장소를 clone 하기
    • 다른 프로젝트에 참여하거나, Git 저장소를 복사하고 싶을 때 사용
    • 해당프로젝트의 히스토리까지 전부 복사해옴
  • File의 라이프사이클

 

  • 처음 저장소를 Clone 하면 => Unmodified 상태
  • Repository에 수정사항 기록하기
    • git add
      • 새로운 파일 트래킹 하기
      • Changes to be committed == Staged 상태
      • 나중에 Commit 할 경우, git add를 실행한 시점의 파일 상태가 Commit 되어 Repository에 기록됨
      • 파일 / 디렉토리 경로를 인자로 받음
    • git status
      • 파일의 상태 확인하기
      • nothing to commit
        • Tracked 파일을 하나도 수정하지 않은 상태
        • Untracked 파일은 아직 존재하지 않은 상태
      • 현재 작업중인 브랜치를 알려줌

.git/objects/ 에 커밋 목록이 있음

  • commit 이란?
    • staged 상태에 있는 변경사항들을 로컬 git repo에 반영하는 명령
    • commit 을 하기 위해서는 commit 메시지가 필요
    • git commit -m "Subject" -m "Description.."
    • commit 의 종류 명시
  • git commit --amend
    : 가장 최근 완료한 커밋 수정하기
    • 마지막 commit 메시지 수정 가능
    • commit 후 git add 한 파일을 이전 커밋에 추가하고 싶을 때 사용 가능
      git add 후 git commit --amend하면 가장 최근 커밋이 수정되면서 git add했던 파일들이 추가됨
  • Commit 메시지 여러개 수정하기
    • 예전 커밋을 수정하려면 rebase 명령 사용
    • git rebase -i <HEAD로 표시 or 커밋 해시값>
      대화형 모드로 rebase 수행
    • git rebase -i HEAD~3
      마지막 3개의 커밋 수정
      • 각 커밋을 처리할 때마다 각 Commit 메시지 수정, 파일 추가 변경 작업 등을 진행 가능
        (오래된 커밋부터 수정됨)
      • 실제로는 4번째 커밋을 기준으로 rebase 진행

  • pick으로 되어있는 부분을 edit으로 변경한 후
    git commit --amend로 커밋 메시지를 수정
    git rebase --continue 명령으로 커밋 작업 종료를 알림
    -> 다음 수정할 커밋이 있으면 넘어가고, 없으면 HEAD로 돌아옴
  • Commit 순서 바꾸기
    -> rebase 창에서 commit 순서를 변경한다.
  • Commit 합치기

squash

-> 저장 후 열리는 창에서 커밋 메시지 수정 가능

  • git log
    : commit history 조회
  • git rm
    : 파일 삭제하기
    • == rm  +  git add
    • Git 에서 파일을 제거하려면 git rm 명령으로 Tracked 상태의 파일을 삭제한 후에 commit 해야 함
    • 그냥 삭제하면 Staging Area에서 파일을 되돌릴 수 있다.
    • commit 까지 완료하면 파일 삭제 후 더는 추적하지 않음
    • Working directory와 Staging area(delete + add)에서 모두 삭제
    • git restore --staged --worktree --source=HEAD README
      git rm 으로 삭제된 파일을 원래대로 돌려놓는 명령
  • git restore --staged
    • staging area의 파일을 HEAD로부터 복구함
    • unstaged 상태로 바꿈
  • git restore (--worktree)
    • working directory 파일을 staging area의 파일로부터 복구
    • working directory에서 지워진 파일을 staging area로부터 복구시킴

3) HEAD 계통 관계

  • HEAD^: HEAD 의 부모 (바로 이전 커밋)
    HEAD^2: HEAD의 바로 이전(머지 전 여러 브랜치의 커밋) 커밋들 중 2번째 커밋
  • HEAD~: HEAD 의 첫번째 부모
    git reset HEAD~ : HEAD의 부모 커밋으로 리셋
  • d932345^2: d932345 의 첫번째 부모들 중 2번째 커밋
    Merge의 경우에만 두번째 부모 존재 (두개가 하나로 합쳐짐)
  • HEAD~2: HEAD의 첫번째 부모의 첫번째 부모
  • HEAD~3^2: 3번째 부모의 (머지 된 커밋들 중)두번째 부모

git reset

  • 1단계: HEAD 이동 (git reset --soft)
    HEAD가 가리키는 Branch를 이동
    -> git add 된 상태, 커밋 전 상태로 이동
    -> 수정사항이 staging area에 반영된 상태

git reset --soft HEAD~1 한 후 상태

  • 2단계: Index (Staging area) 업데이트 (git reset (--mixed))
    Index 를 HEAD가 가리키는 상태로 만듦
    -> staging area에 수정사항이 반영 안된 상태

git reset HEAD~1 후 git 상태

  • 3단계: Working Directory 업데이트 (git reset --hard HEAD~)
    되돌릴 수 없음
    -> HEAD를 아예 옮김. 수정사항 사라짐

  • Restore
    • git restore <file>
      스테이징에 반영되지 않은 파일을 스테이징 영역과 동일한 상태로 복구하는 명령
    • commit 영역과 staging 영역으로부터 파일을 현재 작업 디렉토리에 복구하는 용도
    • Branch를 업데이트하지 않음
    • Commit 히스토리에 영향을 줌
  • Reset
    • git reset 
    • Branch를 업데이트하여, Commit들을 삭제하거나 추가할 수 있음
    • Commit History에 영향을 줌

4) Repository에 수정사항 기록하기

  • .gitignore: 파일 무시하기
    • 어떤 파일은 Git 이 관리할 필요 없음
    • .gitignore 파일을 만들고, 무시할 파일 패턴을 작성
      • 아무것도 없는 라인이나, '#' 로 시작하는 라인은 무시함
      • Glob 패턴
      • / 로 시작하면 하위 디렉토리에 적용되지 않음
      • 디렉토리 표시 -> dir/
      • ! 로 시작하는 패턴 파일은 무시하지 않음
    • *.[oa]
      확장자가 .o , .a 인 파일 무시
    • *~
      ~ 로 끝나는 모든 파일 무시
    • !lib.a
      .a 파일은 무시하지만 lib.a 는 무시하지 않음
    • /TODO
      현재 디렉토리에 있는 TODO 파일은 무시하고 subdir/TODO 처럼 하위디렉토리에 있는 TODO는 반영
    • build/
      build/ dir 모든 파일은 무시
    • doc/*.txt
      doc/abc.txt 파일은 무시하고 doc/server/arch.txt 파일은 무시하지 않음
    • doc/**/*.pdf
      doc/ 아래의 모든 .pdf 파일을 무시
  • git rm --cached
    Staging 에서만 삭제하고 Working Tree 에는 유지
    -> Untracked 파일이 됨
    • .gitignore 파일에 추가하는 것을 빼먹었을 경우
    • 대용량 로그파일이나 컴파일된 .a, .o 파일을 실수로 추가한 경우
    • 여러개의 파일이나 디렉토리를 한번에 삭제
      git rm log/\*.log
      git rm \*~ : ~ 으로 끝나는 파일 삭제
  • Repository 에 수정사항 기록하기
    • git diff
      : Staged 상태와 UnStaged 상태의 변경 내용을 보기
      • Stage 되지 않은 변경점들을 파악하기 위해 사용됨
      • 전부 Staged 상태라면, No output
    • git diff --staged (--cached)
      : Staged 상태와 커밋 상태를 비교
    • git difftool
      다른 툴을 활용하여 변경점 파악 가능

5) Remote Repository

  • git clone
    : 기존 저장소를 clone 하기
    • Clone 시 자동으로 원격 레포지토리가 origin 이름으로 추가됨
    • 자동으로 로컬의 master / main 브랜치가 원격 master / main 브랜치 추적
  • git remote
    현재 프로젝트에 등록된 원격 레포지토리 확인
  • git remote -v
    원격 레포지토리의 이름과 URL 확인
  • git remote show origin
    : origin 의 구체적인 정보 확인
  • git remote add <name> <url>
    : 기존 프로젝트에 새 원격 레포 url 추가
  • git remote rename <old_name> <new_name>
    : repo 이름 변경
  • git remote rm <name>
    : repository 삭제
  • git fetch <remote name>
    : 로컬에는 없지만, Remote Repository에 있는 데이터를 모두 가져옴
    • remote 이름 생략 시 origin 에서 fetch
    • 이후 수정된 것을 모두 가져옴
    • 리모트 저장소의 데이터를 모두 로컬로 가져오지만, 자동으로 Merge 하지는 않음
      -> working dir 의 파일 내용은 변경하지 않음
  • git pull
    = git fetch + git merge FETCH_HEAD
    : 작업중인 코드에 합쳐짐
  • git pull --rebase [remote name]
    : Fetch + 현재 작업 코드와 rebase

Branch 란?

  • Commit 사이를 가볍게 이동할 수 있는 포인터
  • Commit 시 저장되는 것들
    1. 각 파일에 대한 Blob
    2. 파일과 디렉토리 구조에 대한 트리들
    3. 메타데이터와 Root Tree를 가리키는 커밋
    4. 이전 커밋 정보도 저장됨
  • master branch
    • Repository를 처음 만들 때, 만들어지는 기본 브랜치
    • 다른 브랜치와 차별점은 없음
  • git branch <name>
    : 브랜치 생성
    • 새로 만든 브랜치는 지금 작업하고 있던 마지막 커밋을 가리킴
    • git branch 를 생성하고, 브랜치를 옮기지는 않음
  • git switch <name>
    : Branch 변경
    • git switch -c <name>
      : Branch 생성 & 변경
    • git switch -
      : 이전 브랜치로 변경

코드 수정하고 push 하기

git push origin master

  • 원격 레포에 쓰기 권한 필요
  • Clone 이후 아무도 origin repo에 push 안한 경우 사용 가능
  • 즉, push 전에 다른 사람의 작업 사항을 가져와서 merge 한 후에 push 가능

이미 로컬에 있는 브랜치가 Remote 의 특정 브랜치를 추적하게 하려면

  • git branch --set-upstream-to origin/serverfix
  • == git branch -u origin/serverfix

Tracking branch: upstream 브랜치와 직접적인 연결고리가 있는 로컬 브랜치 (fork 레포)

upstream branch: Tracking하는 대상 브랜치 (fork 해온 원래 레포)

  • Branch Tracking
    • git branch -vv
      : 로컬 브랜치 목록과 추적하고 있는 remote branch 목록을 보여주며, 로컬 브랜치가 얼마나 앞서 나가거나 뒤쳐지는지에 대한 내용도 보여줌
      • 마지막으로 서버에서 데이터를 가져온 Fetch 시점을 바탕으로 계산됨
  • Remote Branch 삭제
    • git push <remote 이름> --delete <branch이름>
      : Remote 레포에서 대상 branch 삭제함

5) Stashing

  • Stashing의 필요
    • 작업 중간에 다른 요청이 들어와서 브랜치를 변경
    • 작업 중이던 내용은
      • -> 아직 커밋하지 않은 파일이 변경할 브랜치와 충돌날 경우, 브랜치 변경 불가
      • Branch 변경 전, 작업 디렉토리를 clean 상태로 정리
    • branch랑 상관없이 저장됨
  • git stash push
    : 작업 중인 내용 임시 저장
    • 가장 최근 Commit 시점으로 돌아감
    • 작업 디렉토리는 깨끗해짐
    • tracking 되지 않는 파일 (새로 생긴 파일)은 Stashing 되지 않음
  • git stash list
    저장한 stash 목록 확인
    • branch랑 상관없이 모든 stash 리스트가 다 보임
  • git stash apply <number>
    Stash에 적용했던 내용 복원
    • number는 클수록 가장 오래된 것, 0이 가장 최신
    • 새로운 파일이 add 되어있던 경우, staged 상태로 복원됨
  • git stash apply --index
    Stash에 적용했던 내용을 Staged 상태까지 복원
    • stash 할 때 staging 상태였던 경우에만 staged 상태가 됨
  • git stash drop {0}
    : 해당 Stash 삭제 - 0번째 stash
  • git stash pop
    : Stash에 적용했던 내용 복원 후 stash 제거
    (0번부터 제거됨)
  • git clean
    : 작업하고 있던 내용을 Stashing 없이 제거
    • 추적되고 있지 않은 파일까지 모두 삭제되므로 신중하게 사용해야 함

6) 코드 리뷰 반영하기

  • Pull Request 생성 (머지)
  • 코드 리뷰 후 리뷰 반영
  • 새로운 작업은 새로운 브랜치를 생성하여 시작
  • 수정한 코드 -> git add  -> git commit --amend
    를 통해 커밋에 반영
  • 커밋 해시값이 변경되어 push가 안됨
    -> git push --force origin issue3
    강제로 푸쉬, 다른 사람이 pull 받을때 오류 생길 수 있음

4. 컨테이너 기술과 Docker

4.1 가상화의 개요

  • 가상화
    • 하드웨어에 종속된 컴퓨터 리소스를 추상화
  • 운영체제에서 제공하는 가상화
    • 각각의 응용프로그램이 각자의 CPU, 큰 가상 메모리를 가지고 있는 것처럼 착각하도록 가상화를 제공

4.2 서버 가상화

  • 서버 가상화 도입 배경
    • 하드웨어 기술이 발전하면서, 서버의 성능이 획기적으로 향상됨
    • 예전에는 하나의 컴퓨터에서 한 애플리케이션만 돌릴 수 있었지만 성능 향상으로 한 컴퓨터에서 여러 앱을 실행할 수 있게 됨

서버 가상화

  • 서버 가상화의 장점
    1. 높은 자원 활용률
      • 용도가 다른 3개의 물리 서버를 사용할 경우, 각 서버의 실행 용량의 일부에 불과한 30%만 사용하는 경우, 개별 서버에서 개별 태스크를 실행하는 것이 낭비가 된다.
      • 더 적은 서버로 태스크를 실행할 수 있다.
      • 남은 서버는 활용하거나, 중지하여 냉각 & 유지관리 비용 절감
    2. 장애 고립
      • 특정 애플리케이션이나 OS의 장애가 전체 시스템으로 전파되어 다른 업무에 영향을 미치는 것을 방지한다.
      • 서버 가상화를 하게 되면, 한 OS의 장애로 인한 오류가 다른 시스템에 영향을 미치지 않는다.
    3. 보안 강화
      • 개별 사용자가 자신의 VM에만 접근할 수 있어, 전체 시스템에 대한 접근을 원천적으로 차단 가능
      • 모든 사용자는 자신의 VM에만 접속할 수 있으므로 타 사용자의 데이터에 대한 접근은 불가능
      • 하나의 OS에서 유저를 구분하는 방식은, 설정을 제대로 하지 않으면 다른 유저의 데이터에 접근이 가능해지므로 원천적인 차단은 아님
    4. 신속한 자원 제공 및 백업
      • 설정이 완료된 VM에 대해서 필요 시에 스토리지에서 복사 및 이전함으로써 신속한 자원 제공 및 백업 가능
      • 전력 소모를 줄이고, 로드밸런싱을 위해 백업하거나 마이그레이션
  • 서버 가상화의 단점 (VM)
    • 성능 오버헤드
      • 시스템 자원의 할당/사용을 위해 Hypervisor를 거쳐야 하므로 Bare-metal 방식에 비해서 처리에 부가적인 시간 필요
      • Bare-metal: 물리적인 서버 (가상화 아님)
    • 자원 낭비
      • Guest OS 실행을 위한 자원이 필요
      • CPU, 메모리 등
    • 거대한 이미지 사이즈
      • VM 이미지에는 애플리케이션, 필수 라이브러리 / binary & Guest OS 가 포함됨
      • 이미지 사이즈가 커서 VM migration 이 느리다.
    • 느린 시작 시간
      • CPU, 메모리, 하드디스크 등의 하드웨어를 가상화하고있어 Guest OS를 부팅해야 사용할 수 있음
      • 분 단위 소요

4.3 컨테이너

운영체제 수준의 가상화

  • 컨테이너는 프로세스 간 벽을 만들어 하나의 OS 커널 안에서 애플리케이션이 구동되는 환경을 격리할 수 있음
  • 리눅스 커널의 네임스페이스와 컨트롤 그룹이라는 기술을 기반으로 함

가상 서버와 컨테이너의 차이

컨테이너의 장점

1. 인프라의 사용률 향상

  • GuestOS 실행을 위한 자원 낭비가 없음
  • 일반적인 프로세스 실행과 거의 차이가 없음
  • 하나의 물리 서버에서 프로세스만큼 많이 실행 가능

VM 과 컨테이너의 차이

2. 빠른 기동 시간

  • 컨테이너의 기동 시간은 가상 서버나 물리 서버의 기동시간보다 훨씬 빠르다
  • 컨테이너: app + 의존 패키지 (훨씬 가벼움)
    서버 이미지: OS + app
  • 설치 작업이나 설정 작업이 줄어듬
  • 성능이 VM: 65%, 컨테이너: 90%

3. 불변 실행 환경

  • 기존 문제
    • 개발자는 다양한 라이브러리나 오픈소스로 공개되는 프레임워크를 사용하여 개발을 진행
    • 오픈소스 프로젝트는 빈번하게 버전 업, 버그 수정, 보안 패치 등이 일어난다.
    • 애플리케이션을 빌드할 때마다 다른 라이브러리를 사용하게 될 가능성이 있음
  • 컨테이너
    • 애플리케이션 실행에 필요한 소프트웨어를 모두 포함하고 있음
    • 컨테이너를 조합하여 시스템을 구성함으로써 특정 서버 환경에 대한 종속성을 배제할 수 있음
      (항상 같은 버전의 SW 사용)
    • 개발 환경과 운영 환경의 차이를 줄일 수 있음

5. Docker

: 컨테이너 기반 가상화 도구

  • 2013 Go 언어로 개발
  • Container 관련 기술의 표준
  • 애플리케이션 배포, 테스트에 초점

5.1 Docker 의 아키텍쳐

클라이언트/서버 모델

(클라이언트 역할과 서버 역할 분리)

  • 서버: Docker 데몬
    클라이언트: Docker 클라이언트
    • 클라이언트가 네트워크를 통해서 컨테이너 호스트에 있는 도커 데몬에 요청을 하거나, 같은 호스트에 있는 도커 데몬에 요청을 할 수 도 있다.
  • 이미지, 컨테이너
  • Docker 레지스트리

도커의 아키텍처

Docker 데몬

  • 클라이언트에서 Docker 커맨드를 전달받고, Docker 오브젝트인 이미지, 컨테이너, 볼륨, 네트워크 등을 관리
  • 네트워크 너머에 있는 원격 클라이언트로부터 요청을 받는 것도 가능

Docker 클라이언트 (Docker 커맨드)

  • 컨테이너 조작을 위한 CLI 클라이언트
  • 컨테이너, 이미지, 네트워크, 볼륨 등의 Docker 오브젝트를 관리한다.
    • docker build, docker pull, docker run

Docker 이미지

  • 컨테이너를 기동하기 위한 실행 파일과 설정 파일의 묶음
  • 컨테이너 실행 시 이미지에 담긴 미들웨어나 애플리케이션이 설정에 따라 기동
  • 하나의 이미지는 여러 Layer 의 조합으로 이루어짐
  • 대부분의 이미지는 다른 이미지에 기반하여 만들어짐
    - 실제로는 다른 이미지의 Layer 들을 참조
  • 유니온 파일 시스템(UnionFS) 에 의존

도커 이미지 빌드 순서

  • 이미지를 만들 때는 기반 이미지와 설치 스크립트 등을 Dockerfile에 기재하여 빌드
    예제) Nginx 컨테이너 이미지는 데비안 이미지 기반으로 만들어짐
    1. Docker file은 'docker build' 명령어를 통해 읽혀짐
    2. 기반이 되는 데비안 이미지가 로컬에 없으면 레지스트리로부터 다운받는다.
    3. 데비안 이미지를 컨테이너로 기동
    4. Nginx 패키지 설치, 설정파일 추가
    5. 새로운 이미지를 Nginx 로 로컬 레포에 저장

Docker 컨테이너

  • docker run 명령을 통해 이미지는 컨테이너로 변환되어 하나의 인스턴스가 됨
    이미지 => 컨테이너로 변환됨
  • IP 주소를 가지는 하나의 독립된 서버처럼 동작
  • 중지된 컨테이너를 재기동할 경우, 기존에 할당된 IP 주소 유지 안됨 (기존에 할당된 IP 주소는 재기동시 변경될 수 있음)

이미지와 컨테이너의 관계

  • 컨테이너 실행 과정
    1. 커맨드 실행
      docker run hello-world
    2. 이미지 다운로드
    3. 컨테이너를 만들어서 프로세스 실행
    4. 메시지 표시

컨테이너 실행 개요

  • 컨테이너의 생명 주기
    • 이미지: 실행되기 전의 상태
    • 실행: 컨테이너 위에서 프로세스가 실행중인 상태
    • 정지: 프로세스의 종료 코드, 로그가 보존된 채 정지한 상태

컨테이너의 상태 전이

Docker 레지스트리

  • 컨테이너의 이미지가 보관되는 장소
  • 기본적으로 Docker 허브를 사용
  • 레지스트리 종류
    • 퍼블릭 레지스트리: 누구나 이용할 수 있는 공개 레지스트리 (Docker hub)
    • 클라우드 레지스트리: 퍼블릭 클라우드에서 제공하는 레지스트리 서비스
    • 비공개 레지스트리: 회사나 팀 전용으로 레지스트리를 구축 및 운영
  • 레지스트리와 쿠버네티스의 관계
    • 레지스트리는 개발한 컨테이너 이미지를 쿠버네티스에서 실행하기 위한 중간 창고와도 같은 존재
    • 쿠버네티스에서도 레지스트리에서 이미지를 다운받아 컨테이너를 실행한다.
    • docker build 로 이미지를 빌드, docker push 로 레지스트리에 이미지를 등록, kubectl 커맨드로 매니페스트에 기재한 오브젝트들의 생성을 요청한다. 매니페스트에 기재된 레포로부터 컨테이너 이미지를 다운로드, 컨테이너를 파드 위에서 기동

도커와 쿠버네티스를 연결하는 레지스트리의 역할

Docker 이미지와 컨테이너

  • 이미지는 운영체제와 소프트웨어를 담고있는 컨테이너 실행 이전의 상태
  • 각 이미지는 '리포지터리:태그' 로 식별됨
  • 리포지터리에 올리고 받는 것은 이미지
  • 컨테이너는 이미지를 실행한 상태
  • 이미지로 여러개의 컨테이너를 만들 수 있음
  • 운영체제로 치면 이미지는 실행파일, 컨테이너는 프로세스

Docker를 이용한 컨테이너 애플리케이션 서비스는, 컨테이너 동작에 필요한 모든 내용을 코드로 작성하여 변경 불가능한 인프라 환경에서 애플리케이션 개발, 배포, 테스트가 가능하다. 같은 이미지를 사용하기 때문에 항상 같은 환경에서 작업할 수 있다.

5.2 Docker 실습

  • docker pull 로 busybox 이미지를 다운로드한 후 조회
  • DIGEST: 이미지에 할당된 해시값
  • IMAGE ID 는 레이어의 해시값을 나타낸다. 12글자
  • 태그가 없으면 자동으로 :latest 태그가 붙는다.

이미지로부터 컨테이너 실행 - run

$ docker run busybox
$ docker ps -a

$ docker run -it busybox sh
# uname -a
// 커널 버전 확인 (host OS 와 동일함)
  • 다운로드한 이미지를 실행하면 컨테이너가 된다.
  • 이미지 뒤의 태그가 latest 이면 생략 가능
  • 컨테이너는 호스트의 커널을 공유해서 사용
  • 가동에 필요한 도구만 일부 탑재한 "격리된 경량의 리눅스 프로세스"
$ docker run busybox echo 'hello world'
hello world

hello world 문자열의 출력은 호스트가 아닌 컨테이너의 실행 결과이다.

busybox 실행 과정

  • Docker 실행 원리
    • 클라이언트는 Docker 명령을 수행하는 명령줄을 제공
    • 수행된 Docker 명령은 서버의 Docker Daemon으로 전달
    • Docker daemon 은 docker.socket 이 보유한 Docker API를 이용해 컨테이너를 생성
    • 수행된 컨테이너에 포함된 서비스 결과를 클라이언트에 전달

5.3 Docker 명령

docker 이미지 관련

  • 이미지 검색하기
    docker search 이미지명[:TAG]
    • OFFICIAL 에 ok 표시 있는 이미지가 공식
  • docker 이미지 내려받기
    docker [image] pull [OPTIONS] 이미지명[:TAG]
    docker pull
    • docker image pull debian
    • 태그 대신 다이제스트 값 지정 가능 (이미지명:sha256:asdf123..)
  • 이미지의 기본 형식
    <네임스페이스>/<이미지명>:<태그>
    • 네임스페이스를 지정하지 않으면 docker hub 의 library 가 기본으로 지정된다.
    • 이미지명 뒤에 :TAG 를 포함하지 않으면 자동으로 latest 로 지정
    • 도커 허브 레지스트리 명시적 지정 (공개 레지스트리)
      • library/debian:latest
      • docker.io/library/debian:latest
      • index.docker.io/library/debian:latest
    • 외부 레지스트리 주소 - http를 붙이지 않고 이미지 주소를 써야 한다
      docker pull gcr.io/google-samples/hello-app:1.0

Docker hub 에서 debian 이미지 받기

  • 다운로드한 이미지 정보가 로컬에 저장되었음을 표시
  • 해시값 -> 하나의 레이어를 나타냄 (이미지 id)
  • DIGEST 값은 도커 레지스트리에서 관리하는 해시값
  • docker 이미지 목록 출력
    docker image ls
  • docker 이미지 세부 정보 조회
    docker image inspect [OPTIONS] 이미지명[:TAG]
    • Id: 이미지 id
    • Created: 생성일
    • DockerVersion: Docker 버전
    • Architecture: CPU 아키텍처
    • RootFS: 이미지 다이제스트 정보
    • GraphDriver: 이미지 레이어 저장 정보
    • Env: 이미지 환경변수 세팅
    • Cmd: 컨테이너 만들 때 자동으로 실행되는 명령
    • WorkingDir: 컨테이너를 만들었을 때 시작 경로
  • Docker 이미지 히스토리 조회하기
    docker image history [OPTIONS] 이미지명[:TAG]
    • 이미지 구성 레이어의 수행 명령, 크기 등을 조회
    • 위쪽 내용이 최신 변경 내역
    • 사이즈 표기된 부분 ==> 레이어가 생성된 부분
      사이즈가 없어도 레이어가 추가되었을 수 있음
    • Image != Layer
      이미지는 여러개의 레이어로 구성된다.
      한번 다운반은 레이어는 read-only 로, 재활용이 가능하다.
  • Docker 이미지 태그 설정하기
    docker image tag 원본이미지명[:TAG] 참조이미지명[:TAG]
    • docker  images  원본이미지명:tag  (new)참조이미지명:tag
    • 원본 이미지와 같은 이미지 아이디로 이름과 태그만 다르게 생성된다
  • docker login
    도커 로그인
    • host에서 docker hub 에 이미지를 업로드하기 위해서는 로그인이 필요
    • docker logout
    • docker info
  • docker 이미지 삭제하기
    docker image rm [옵션] { 이미지명[:tag] | 이미지 id }
    docker rmi [옵션] { 이미지명[:tag] | 이미지 id }
    • 다른 이미지가 참조하고 있는 이미지는 삭제할 수 없다.
  • 모든 Docker 이미지 삭제하기
    docker image prune
    • 로컬에 다운로드한 이미지 중 하나 이상의 컨테이너가 연결되지 않은 모든 이미지를 제거
    • Dangling 이미지 모두 삭제됨
      • 태그가 붙지 않은 이미지
      • 어떤 컨테이너도 참조하지 않는 이미지
    • docker image prune -a : 사용중이 아닌 모든 이미지가 제거됨 (연결된 컨테이너가 없는 것)

Docker 컨테이너 관련 명령

  • 컨테이너 목록 출력
    • docker container ls
    • docker ps
    • -a 옵션: 정지된 컨테이너까지 모두 출력
    • 옵션을 사용하지 않으면 실행되고 있는 컨테이너만 출력
  • 컨테이너 실행하기
    • docker [container] run 이미지명 [실행명령]
      docker run 이미지명 [실행명령]
    • 이미지를 기반으로 컨테이너를 실행시킴
    • run == pull + create + start
    • 옵션
      • -i
        키보드의 입력을 컨테이너의 표준 입력에 연결하여 키보드 입력을 컨테이너의 쉘에 보냄
      • -t
        터미널을 통해 대화형 조작이 가능하게 한다.
      • -d
        백그라운드로 컨테이너를 돌려 터미널과 연결하지 않는다.
      • --name
        컨테이너에 이름을 설정한다. 시스템에서 유일한 이름이어야 하며, 옵션을 생략하면 자동으로 만들어진 이름이 부여된다.
      • --rm
        컨테이너가 종료되면 종료 상태의 컨테이너를 자동으로 삭제한다. (매번 같은 이름으로 컨테이너를 생성할 수 있게됨)
      • --restart : 컨테이너 종료 시 적용할 재시작 정책 지정
      • --env : 컨테이너의 환경변수 지정
      • -v, --volume : 호스트 경로와 컨테이너 경로의 공유 볼륨 설정
      • -h : 컨테이너의 호스트명 지정
      • -p [host port]:[container port], --publish : 호스트 포트와 컨테이너 포트 연결
      • -P, --publish-all=[true | false] : 컨테이너 내부의 노출된 포트를 호스트 임의의 포트에 게시
      • --link=[container:container id] : 동일 호스트의 다른 컨테이너와 연결 설정으로 IP가 아닌 컨테이너의 이름을 이용해 통신
  • 컨테이너 생성하기
    • docker [container] create [옵션] 이미지명
      docker create [옵션] 이미지명
    • 이미지를 기반으로 컨테이너를 생성
    • docker container create -it --name container-test1 ubuntu:14.04

docker create

  • 컨테이너 시작하기
    • docker [container] start [옵션] 컨테이너명
      docker start [옵션] 컨테이너명
    • 이미 생성한 컨테이너를 시작한다.
  • 실행중인 컨테이너 접속하기
    • docker [container] attach [옵션] 컨테이너명
      docker attach [옵션] 컨테이너명
    • 동작중인 컨테이너에 접속
    • 원래 실행명령이 /bin/bash 이기 때문에 명령을 자유롭게 입력할 수 있음
      • 단 DB나 서버 애플리케이션을 실행하면 출력만 확인 가능
      • Bash 쉘에서 exit 또는 Ctrl + D 를 입력하면 컨테이너가 정지됨
      • 여기서는 Ctrl + P + Q 를 입력하여 컨테이너를 정지하지 않고 빠져나옴
  • 컨테이너 삭제하기
    • docker [container] rm [옵션] 컨테이너명
      docker rm [옵션] 컨테이너명
    • 컨테이너를 삭제
    • -f 옵션을 통해 동작 중인 컨테이너도 삭제 가능
  • 컨테이너를 정지할 때 함께 삭제하기
    • docker [container] run --rm [옵션] 이미지명
      docker run --rm [옵션] 이미지명
    • 실행이 끝나면 자동으로 파기됨
    • docker container rm 으로 삭제할 수도 있음
  • 실행중이지 않은 모든 컨테이너 삭제하기
    • docker container prune [옵션]
    • 실행 중이 아닌 컨테이너들도 저장공간 차지함
      => 실행 중이 아닌 모든 컨테이너 일괄 삭제
  • 실행중인 컨테이너 정지하기
    • docker [container] stop 컨테이너명
      docker stop 컨테이너명
    • -t 10 : 10초 후 정지
  • 컨테이너 재시작하기
    • docker [container] restart 컨테이너명
      docker restart 컨테이너명
    • 기존 컨테이너 프로세스를 정지하고 새로운 컨테이너 프로세스를 시작
    • 컨테이너 동작에는 영향을 주지 않고, 호스트의 PID 만 변경
  • 외부에서 컨테이너 안의 명령을 실행
    • docker exec -it ba32nsdn2 bash
    • docker container run -d --name httpd:latest  컨테이너 실행 후
      docker container exec -it httpd /bin/bash 접근 가능
    • 컨테이너가 실행되고 있는 상태에서만 사용할 수 있으며 정지된 상태에서는 사용할 수 없음
    • docker exec 명령은 이미 실행된 컨테이너에 apt-get, yum 명령으로 패키지를 설치하거나 각종 daemon 을 실행할 때 활용
  • 컨테이너 표준 출력을 호스트에 연결하기
    • docker container logs 컨테이너명
    • 현재 실행 중인 특정 Docker 컨테이너의 출력 내용을 확인
    • 실행되면서 출력한 메시지 확인
    • -f 옵션 사용 시 새로 출력되는 내용이 계속 출력됨
  • 컨테이너와 호스트 간 파일 복사하기 docker cp
    • docker [container] cp 컨테이너명:원본파일 대상파일
    • docker [container] cp 원본파일 컨테이너명:대상파일
    • 실행/정지 상태의 컨테이너와 호스트 간에 파일을 복사하기 위한 명령
  • 컨테이너 사용 현황 확인하기 docker stats
    • docker [container] stats 컨테이너명
    • 컨테이너들의 시스템 리소스 사용 현황 확인
    • 리눅스 계열 운영체제의 top 명령어와 비슷한 역할
  • 컨테이너에서 변경된 파일 확인 docker diff
    • docker [container] diff 컨테이너명
    • 컨테이너가 실행되면서 변경된 파일 및 디렉토리 목록을 출력
      • A: 추가된 파일
      • C: 변경된 파일
      • D: 삭제된 파일
    • 비교 기준: 컨테이너를 생성한 이미지 내용과 비교
  • 컨테이너의 세부 정보를 출력 docker inspect
    • docker [container] inspect 컨테이너명
  • 컨테이너의 변경사항을 이미지로 생성 docker commit
    • docker [container] commit [옵션] 컨테이너명 이미지명[:태그]
    • -a: Author
    • -m: 커밋 메시지

 

1) run / start 차이

  • run : 새로운 컨테이너를 이미지로부터 만듦
    • docker container run IMAGE_ID
  • start | stop : 기존에 실행되었던 컨테이너를 중지 | 실행 시킴
  • docker container start CONTAINER_ID
  • docker container stop CONTAINER_ID

5.4 Docker Volume

  • 컨테이너의 문제점
    • 이미지로부터 컨테이너 생성 후 모든 파일 변경사항들은 Writable layer 에 반영됨
    • 컨테이너 내부의 데이터는 컨테이너의 라이프사이클과 연관됨
      (read-only 레이어들 위에 writable 한 레이어에 데이터를 쓰므로 데이터는 컨테이너에 종속된다.)
    • 컨테이너에서 생성된 데이터를 영구적으로 유지하기 위해서는 컨테이너 서비스에서 데이터와 로직의 분리가 필요
  • Docker Volume
    • 데이터와 컨테이너를 분리하는 역할
    • <호스트 파일 시스템 디렉토리> - 연결 - <컨테이너의 디렉토리>
    • 컨테이너가 삭제되어도 volume은 독립적으로 운영 가능
    • 컨테이너에서 write 한 data 들이 실제로는 host 의 디렉토리에 쓰여져있기 때문에 컨테이너가 삭제되어도 데이터는 남아있다.
  • docker volume 이 만들어지지 않은 상태더라도 컨테이너 실행 시 volume 이름을 쓰면 volume 타입으로 자동 생성됨
  • 연결된 컨테이너가 있으면 볼륨 삭제할 수 없음

Docker Volume 타입

도커 볼륨 레퍼런스 참조

  1. volume
    • Host 파일 시스템에 docker 영역을 만들어서 자동으로 컨테이너에서 volume을 연결만 하면 어디에 쓰는지 몰라도 사용이 가능하다.
    • Docker 에서 권장하는 방법
    • volume 생성 방법
      docker volume create 볼륨 이름
    • 여러 컨테이너가 공유 가능
    • volume 드라이버를 통해 원격 호스트 및 클라우드 환경에 volume 내용을 저장하고 암호화 가능
    • 기존 volume 을 컨테이너에 연결하면 바로 데이터 사용 가능
    • docker area 에 알아서 볼륨이 생성됨
    • 기존에 존재하지 않는 볼륨은 자동으로 생성됨
    • 볼륨 지정 방법
      • --mount
        • docker run -d --name vol-test1 --mount source=my-appvol-1,target=/app ubuntu:20.04
      • -v
        • docker run -d --name vol-test2 -v my-appvol-1:/var/log ubuntu:20.04
      • 존재하지 않는 볼륨
        • docker run -d --name vol-test3 -v my-appvol-2:/var/log ubuntu:20.04
          -> 자동으로 생성됨

2. bind mount

  • Host 의 디렉토리와 컨테이너의 디렉토리를 연결
  • volume에 비해 사용이 제한적
  • 호스트 파일 시스템 절대경로 : 컨테이너 내부경로 를 직접 마운트하여 사용
  • 사용자가 파일 또는 디렉토리를 생성하면 해당 호스트 파일 시스템의 소유자 권한으로 연결
    • 존재하지 않는 경우 자동으로 생성
    • 자동 생성된 디렉토리는 Root 사용자 소유
  • 컨테이너 실행 시 지정하여 사용
  • 컨테이너 제거 시 바인드 마운트는 해제되지만 호스트 디렉토리는 유지됨
  • 만들어지지 않은 컨테이너의 디렉토리에, 읽기 쓰기 권한 여부를 설정할 수 있다.
    • -v <호스트파일 절대경로>:<컨테이너파일경로>:<옵션>
      • 옵션
        • ro : read-only, 읽기 전용 옵션
        • rw : read-write, 읽기 쓰기 가능
        • 디렉토리에 rwx 로 표시되는 것은 아니지만, 읽기 전용 디렉토리는 파일 생성 불가

bind mount 지정하기

  • bind-mount 볼륨 지정 방법
    • --mount
      • mkdir /home/hylee/target
        docker run -d -it --name bind-test1 --mount type=bind,source="$(pwd)"/target,target=/var/log centos:8
    • -v
      • docker run -d -it --name bind-test2 -v "$(pwd)"/target:/var/log centos:8

3. tmpfs mount

  • Host 의 파일 시스템과 연결
  • 인메모리 파일 시스템 (DRAM) => 휘발성
    • 매우 빠름
    • 임시로 쓸 때 사용
  • 임시적으로 호스트 메모리에서만 지속
  • 컨테이너가 중지되면 tmpfs 마운트가 제거되고 내부에 기록된 파일은 유지되지 않음
  • 호스트 또는 컨테이너에서 지속할 필요는 없지만 중요한 파일을 임시로 저장하고자 할 때 활용
  • 컨테이너 실행 시 지정하여 사용
  • 컨테이너 해제 시 자동 해제됨
  • tmpfs mount 볼륨 지정
    • --mount
      • docker run -dit --name tmpfs-test1 --mount type=tmpfs,destination=/var/www/html httpd:2
    • --tmpfs
      • docker run -dit --name tmpfs-test2 --tmpfs /var/www/html httpd:2
    • tmpfs 마운트된 컨테이너 조회
      docker inspect tmpfs-test2
      "Tmpfs": { "/var/www/html": "" }

5.5 Docker Network

  • Docker 컨테이너는 Docker 네트워크를 통해 다른 컨테이너 또는 다른 애플리케이션 워크로드와 연결 가능
    • docker0 가상 이더넷 브릿지 네트워크를 통해 같은 호스트 컨테이너 간 통신이 가능
    • 같은 host의 컨테이너는 할당된 IP 주소로 통신 가능

도커 브리지 네트워크 연결

  • 컨테이너 간 연동과 외부 공개

컨테이너 간 연동과 외부 공개

  • 내부 네트워크 간 접속의 경우, 호스트 내에서 접근 가능 가능한 전용 네트워크를 통해 애플리케이션과 데이터베이스를 연결한다
  • 컨테이너를 호스트의 외부 네트워크에 공개하는 것도 가능

컨테이너 네트워크의 종류

  1. 기본 Bridge 네트워크 (docker0)
    1. 컨테이너 실행 시 기본으로 연결되는 네트워크
    2. 각 컨테이너에 할당된 IP 주소를 활용해서 서로 접근 가능
  2. 사용자 정의 Bridge 네트워크
    1. 사용자가 새롭게 생성하는 Bridge 네트워크
    2. IP주소 또는 컨테이너 이름을 가지고 서로 접근 가능

docker container network 커맨드

docker network ls 컨테이너 네트워크를 리스트로 표시
docker network inspect 네트워크명을 지정해서 자세한 내용 표시
docker network create 컨테이너 네트워크를 생성
docker network rm 컨테이너 네트워크 삭제
docker network connect 컨테이너를 컨테이너 네트워크에 접속
docker network disconnect 컨테이너를 컨테이너 네트워크에서 분리
  • 컨테이너 실행 시
    • --net <네트워크명> 옵션으로 연결
    • 같은 네트워크에 포함된 컨테이너들 끼리는 컨테이너 이름을 통해 접근 가능
  • 컨테이너에 환경변수 전달 = -e KEY=value

5.6 Docker 이미지 빌드

이미지 빌드 개요

  1. 베이스 이미지 선택
    alpine, busybox 많이 씀
  2. 소프트웨어 패키지 설치
    • 애플리케이션 실행에 필요한 소프트웨어 패키지 설치
    • 패키지 매니저
      apt (ubuntu), yum (centos)
      pip (python), npm (node.js)
  3. 애플리케이션 소스 코드 복사
  4. Dockerfile 작성
    • Dockerfile 에 작성된 대로 이미지를 생성하게 됨
      • 베이스 이미지의 리포지터리
      • 설치할 패키지
      • 애플리케이션 코드와 설정 파일
      • 컨테이너 기동 시 실행될 명령어
        Dockerfile --(build)--> Docker Image --(run)--> docker container

docker file - container 개발

빌드 실행 순서

  1. 디렉토리를 준비하여 이미지에 포함시킬 파일을 모음
  2. Dockerfile 을 작성
  3. 컨테이너에서 실행할 애플리케이션 코드를 작성하고 유닛 테스트를 실행
  4. 이미지를 빌드
  5. 컨테이너를 실행하고 동작을 확인

이미지 빌드 시 특정 파일 무시  - .dockerignore

  • Docker 이미지 빌드
    docker image build -t php-apl:0.1 <Dockerfile 경로>
    • 옵션
      • -t : "이미지명:태그"를 지정
      • -f : Dockerfile이 아닌 다른 파일명을 사용하는 경우에 사용
        -f ./src/Dockerfile_s
    • 경로
      • 현재경로에 Dockerfile -> . 사용
      • Dockerfile 절대 경로 작성도 가능

Dockerfile 작성

FROM <이미지>:[태그] 컨테이너의 베이스 이미지를 지정
Build 시, FROM 으로 지정된 이미지를 먼저 다운로드함
RUN <커맨드>
RUN ["커맨드", "파라미터1", "파라미터1"]
FROM의 베이스 이미지에서 커맨드를 실행
  • Docker 이미지를 빌드할 때 컨테이너 안에서 실행할 명령을 정의하는 Instruction
  • 여러 설치 명령을 연결하여 RUN 커맨드의 수를 줄이면 이미지의 레이어 수가 감소
  • 변경사항을 만드는 커맨드마다 새로운 레이어가 된다.
  • FROM 이미지를 베이스로 만든 임시 컨테이너에서 여러 명령을 실행한 뒤 컨테이너를 이미지로 만들고 임시로 만들어진 컨테이너와 이미지들은 전부 삭제함
ADD <소스> <컨테이너 내 경로>
ADD ["소스", ,"<컨테이너 내 경로>"]
소스(파일, 디렉터리, tar, URL)를 컨테이너 내의 경로에 복사
  • 파일을 이미지 안에 추가
    • 호스트 환경의 파일, 디렉토리를 이미지 안에 복사
    • URL 주소에서 직업 다운로드하여 이미지 안에 추가
    • 압축 파일은 지정한 경로에 압축을 풀어서 추가
  • 제약조건
    • 빌드 작업 디렉토리 외부 파일은 ADD 불가
    • 디렉토리 추가 시 dir/ 로 끝나야 함
COPY <소스> <컨테이너 내 경로>
COPY ["소스", ,"<컨테이너 내 경로>"]
소스(파일, 디렉토리)를 컨테이너 내 경로에 복사
- 단순한 복사 작업만 지원
- 빌드 작업 디렉토리 외부의 파일은 복사할 수 없다.
ENTRYPOINT 커맨드
ENTRYPOINT ["실행가능한것", "파라미터1", "파라미터2"]
컨테이너가 실행하는 파일을 설정
  • CMD와 마찬가지로 생성된 이미지가 컨테이너로 실행될 때 사용되는 명령어 및 인자 설정
  • docker run 실행 시 override 불가
  • 이미지를 생성하는 사람이 컨테이너의 용도를 어느정도 제한하려는 경우에 유용
ex)
ENTRYPOINT ["python"]
CMD ["runapp.py"]
CMD ["실행가능한것", "파라미터1", "파라미터2"]
CMD <커맨드>
CMD ["파라미터1", "파라미터2"] (ENTRYPOINT의 파라미터)
컨테이너 기동 시 실행될 커맨드를 지정
  • 생성된 이미지를 컨테이너로 실행할 때 실행되는 명령을 지정
  • 여러개의 CMD 를 작성해도 마지막 하나만 처리됨
  • RUN vs CMD
    RUN은 이미지를 빌드할 때 실행되고, CMD는 컨테이너를 시작할 때 한번 실행
ENV <key> <value>
ENV <key>=<value> ..
이미지 안에 환경변수 설정
RUN, WORKDIR, 컨테이너에서 사용 가능
EXPOSE <port> .. 공개 포트 표시
실제로는 docker run -p host:container 포트를 연결하여 설정함
USER <user명> | <UID> RUN, CMD, ENTRYPOINT 실행 유저 지정
- 컨테이너의 기본 사용자를 root 가 아닌 다른 사용자로 변경하고자 하는 경우 사용
VOLUME ["/path"] 공유 가능한 볼륨을 마운트
- Docker volume을 미리 설정하는 경우 사용
- volume으로 지정된 컨테이너의 경로는 볼륨의 기본경로(/var/lib/docker)와 자동으로 연결
WORKDIR /path RUN, CMD, ENTRYPOINT, COPY, ADD 의 작업 디렉토리 지정
- 컨테이너 상에서 작업할 경로 전환을 위해 사용
- 지정한 경로가 없으면 자동으로 생성
- 컨테이너 접속 시 지정한 경로로 연결됨
ARG <이름>[=<디폴트 값>] 빌드할 때 넘길 인자를 정의
--build-arg <변수명>=<값>

- docker build 시점에 변수 값 전달을 위해 사용

$ docker build --build-arg db_name=db .
CMD db_start.sh -h 127.0.0.1 -d ${db_name}
LABEL <key>=<value> <key>=<value> 이미지의 메타데이터에 라벨을 추가
MAINTAINER <이름> 이미지의 메타데이터에 저작권을 추가
이미지를 빌드한 작성자 이름과 이메일 작성

로컬 환경에서

export DOCKER_BUILDKIT=1

사용 시

원래는 순차적으로 이미지를 빌드하지만, buildkit 사용 시 병렬로 처리하기 때문에 속도가 빨라진다.

 

반응형

'sswu' 카테고리의 다른 글

독일어 정리  (0) 2022.04.15
디자인패턴 중간 정리  (0) 2022.04.03
[네트워크 분석 실습] 네분실 기말 정리  (0) 2021.11.19
파이썬 기말 정리  (0) 2021.11.15
[모바일SW] 기말 정리1  (0) 2021.11.08
Comments