이 섹션의 다중 페이지 출력 화면임. 여기를 클릭하여 프린트.

이 페이지의 일반 화면으로 돌아가기.

Infra

인프라

1 - 운영체제/OS

운영체제에 기본 지식에 대한 정리하였다.

1.1 - 운영체제 개요

운영체제

운영체제란 (OS : Operating System) 는 컴퓨터 하드웨어가 컴퓨터 소프트웨어와 통신하고 작동하도록하는 소프트웨어 프로그램이다.

  • 하드웨어 자원들과 정보를 최대한 효율적 으로 운영하기 위해 하드웨어와 사용자 프로그램 사이에 존재하는 시스템 프로그램을 의미한다.
  • 컴퓨터를 부팅시키고 운영하는 프로그램이다.
  • 운영체제의 선택에 따라 사용하는 응용프로그램이 달라진다.
  • 운영체제의 종류에 의하여 PC, 서버등으로 컴퓨터의 용도가 결정된다.

컴퓨터를 운영하는 프로그램의 분류

  • 소프트웨어
    • 애플리케이션
      • 워드
      • 게임
      • 그래픽
      • 기타 애플리케이션
    • 운영체제
      • Windows
      • UNIX
      • Linux
      • MacOS
      • 기타 OS

시스템 소프트웨어

컴퓨터를 운영하기 위한 프로그램과 프로그래밍 언어를 해석하는 컴파일러 등을 시스템 소프트웨어라고 한다.

  • 예) 운영체제

응용 소프트웨어

사용자가 실제 업무 처리를 하기 위해 사용하는 프로그램을 응용 소프트웨어라고 한다.

  • 예) 워드프로세서, 스프레드시트, 데이터베이스, 컴퓨터 그래픽 소프트웨어, 게임 소프트웨어 등

드라이버

컴퓨터에 설치된 하드웨어를 구동하는 프로그램을 드라이버리고 한다.

  • 예) 비디오카드 드라이버, 사운드카드 드라이버, 모뎀 드라이버 등

운영체제의 주요 목적

운영 체제의 두 가지 주요 목적이 있다.

  • 컴퓨터 시스템의 계산 활동을 관리하여 컴퓨터 시스템이 제대로 작동하도록 한다.
  • 프로그램 개발 및 실행을 위한 환경을 제공한다.

운영체제의 목표

운영체제는 사용자의 편의성을 향상시키고, 시스템 성능을 극대화를 목표로 한다.

  • 처리능력 향상 : 정해진 시간 내에 최대한 많은 양의 데이터를 처리
  • 응답시간 단축 : 처리 요청에서 처리 완료까지 걸리는 시간을 최소화
  • 신뢰도 향상 : 시스템 장애의 처리
  • 사용 편리성 향상 : 사용자의 사용 환경의 편리성 추구

운영체제의 구성

운영체제를 구성하는 두 가지 요소는 컴퓨터를 제어하는 프로그램과 프로그램을 수행하고 데이터를 처리하는 처리 프로그램이다.

  • 제어프로그램

    • 시스템 전체의 작동 및 프로그램 실행 상태를 감시
    • 사용자가 의뢰한 작업의 시작, 실행 등 작업의 흐름을 관리하고 처리하기 위한 프로그램
    • 입출력과 관련된 데이터를 총괄하여 관리하는 프로그램
  • 처리프로그램

    • 어셈블러(Assembler), 컴파일러(Compiler), 인터프리터(Interpreter)등 고급언어로 작성한 원시 프로그램을 기계가 이해할 수 있는 기계어로 번역하기 위한 프로그램
    • 응용소프트웨어
    • 유틸리티

파티션의 이해

파티션이란 논리분할영역이란 의미를 가진다. 물리적인 하드디스크는 OS에 의한 논리적인 드라이브로 인식되는 절치가 필요하 며 파티션이란 OS가 하드디스크라는 물리적인 장치에 자신이 사용할 논리 영역 을 설정하는 작업이다.

하나의 OS가 하드디스크를 이용하려면 크게 두 가지의 절차를 거쳐야 한다. 하나 는 디스크 공간의 일부 또는 전부를 자신의 영역으로 선언하는 파티션 설정이고 또 다른 하나는 FORMAT을 통한 파일의 입출력 구조를 만드는 것이다.

파티션이 설정되지 않은 디스크는 인식할 수 없다.

하드디스크를 여러 개의 논리 드라이브로 분할 사용하는 것은 사용자의 선택이 다.두 가지의 OS를 복합 설치하는 경우에는 필히 분할한다.

커널

커널은 OS의 모든 부분에 대한 기본 서비스를 제공하는 컴퓨터 운영 체제의 핵심이자 가장 중요한 부분이다.

CPU, GPU

  • CPU(central processing unit)
    • 입출력장치, 기억장치, 연산 장치 등을 포함한 컴퓨터 리소스를 관리하는 최상위 계층의 중앙처리장치이다.
  • GPU(graphics processing unit)
    • 그래픽 처리 장치
    • 반복적이고 비슷한 대량의 연산을 수행하며 이를 병렬적(parallel)으로 나누서 작업하기 때문에 CPU에 비해 속도가 압도적으로 빠르다.

메모리

  • 컴퓨터에서 작업을 수행하기 위해 처리 대상이나 결과 등을 저장하기 위한 공간이다.
  • 프로그램을 실행하기 위한 정보들을 메모리에 저장되어 처리된다.

힙 영역과 스택 영역의 차이점

프로그램이 실행되기 위해 프로그램이 메모리에 로드가 되어야 한다. 따라서 운영 체제에서 프로그램의 실행을 위한 다양한 메모리 공간을 제공한다.

  • 코드, 데이터 스택, 힙 영역이 할당되고 각 역활은 다음과 같다.
    • 코드
      • 실행할 프로그램의 코드가 저장되는 텍스트 영역이다.
      • CPU는 코드 영역에서 저장된 명령어를 하나씩 가져가서 처리한다.
    • 데이터
      • 전역 변수와 정적 변수가 이에 해당된다.
      • 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸된다.
    • 스택
      • 스택 영역은 함수의 호출과 관계되는 지역 변수와 매개 변수가 저장되는 영역이다.
      • 함수의 호출과 함께 할당되며, 함수의 호출이 종료될 때 해제된다.
      • 힙 영역은 사용자가 직접 관리할 수 있는 메모리 영역이다.
      • 힙 영역은 사용자에 의해 메모리 공간이 동작으로 할당되고 해제된다.

2 - Linux

Linux

리눅스 명령어에 대한 정리하였다.

2.1 - Linux 명령어 | Linux 소개

유닉스 역사

Unix는 1969년 AT&T 벨 연구소인 켄 톰슨, 데니스 리치, 브라이언 카니한이 개발한 OS이다. 원래 벨 연구소에서 “Multics"라는 멀티 태스킹 OS를 개발했지만 시스템이 너무 커졌다. 그러나 Multics에서 놀이로 개발한 “Space Travel"이라는 게임을 할 목적으로 연구소의 한 구석에서 먼지를 쓰고 있던 DEC사의 PDP-7이라는 컴퓨터상에 Multics의 소형판이라고도 할 OS 를 개발하다. 이것은 Unix의 시작이다.

다양한 UNIX

Unix계 OS는 각사, 각 단체가 독자적인 강화를 실시해 System V(AT&T), BSD(California 대학 Berkeley교), Solaris(Sun Microsystems), HP-UX(HP), AIX(IBM), XENIX(Microsoft ), UnixWare(Novell), FreeBSD, NetBSD, OpenBSD 등 다양한 종류와 버전의 것이 개발되어 왔다. Unix계 OS의 표준화 단체(UNIX International, OSF, X/Open…)도 몇개가 발족 및 통폐합되어 현재는 The Open Group이라는 단체가 표준화를 행하고 있다.

UNIX와 Unix

“UNIX"라는 명칭은 The Open Group이 상표를 관리하고 있으며, IEEE가 정하는 Unix계 OS의 표준 사양인 “POSIX"를 확장한 “Single UNIX Specification"이라는 표준 사양을 만족하는 것만이 “UNIX"를 자칭할 수 있다. 그런데, 이 사양을 충족하는 것은 많지 않다. 사양을 충족하지 않는 OS는, “UNIX"가 아닌 “Unix계 OS"나, 소문자를 섞은 “Unix"라고 표기된다.

Linux 등장

헬싱키 대학(핀란드)의 리누스 토르발즈(Linus Torvalds)가 1991년 11월에 개발한 Unix계 OS의 하나이다. 오픈 소스로 공개되어 PC에서도 동작하기 때문에 급속히 퍼졌다. 엄밀히 말하면 Linux는 OS 커널 전용 이름이다. 이것에 GNU 프로젝트가 개발한 C언어 컴파일러(gcc)등의 각종 기본 소프트웨어를 더한 것을 GNU/Linux라고 부른다. 또, GNU/Linux 를 베이스로 인스톨러나 패키지 관리 시스템등을 추가한 각종 “Linux 배포판"이 존재한다.

운영체제 (Operating System) 컴퓨터를 활용적으로 사용할 수 있게 인터페이스를 구축한 것이다. ex) Window, Mac, Linux, Unix

Linux 배포판

초기에는 TurboLinux, Miracle Linux, Debian, Red Hat Linux 등 다양한 배포판이 난립했다. 현재는 데비안계와 Red Hat계가 주류가 되고 있다. 데비안계에서는, 염가판 PC용 OS로서도 채용되고 있던 우분투가 자주 이용되고 있다. Red Hat Linux는 상용 안정성을 향상시킨 Red Hat Enterprise Linux(RHEL)와 실험적으로 최신 기술을 통합하는 Fedora로 분화되었다. RHEL 호환 무료 CentOS도 자주 사용된다.

추기: CentOS는 RHEL의 무료 버전에 가깝다.

Unix/Linux 사용처

당초의 Unix계 OS는 주로 엔지니어링계의 업무에 사용되었지만, 현재는 Web 서버, 메일 서버, 라우터 등의 네트워크 기기, TV나 카 내비게이션 등 다양한 용도에 사용되고 있다. Mac도 Mac OS X에서 BSD Unix를 기반으로 다시 작성되었다. Google의 Android도 Linux를 기반으로 한다. Unix/Linux의 대국이라고도 할 수 있는 Microsoft Windows도 Unix계 OS라고까지는 불려지지 않지만, Unix계 OS의 기술이나 사상을 조금만 도입하고 있다.

Linux의 특징

  • 권한을 갖는다.
    • 리눅스 시스템은 “소유권/허가권” 이라는 두 가지 권한을 사용한다.
  • 다중 사용자 환경을 지원한다.
    • 리눅스 시스템은 Multi-Users 및 Multi-Tasking 환경을 사용하므로 다수의 사용자가 한 번에 작업이 가능하다.
  • 대/소문자를 구분한다.
    • “Caps Lock"키의 On/Off를 확인해야 한다.
  • Windows의 파일 확장자 개념이 없다.

TUI와 GUI

  • TUI (Text User Interface)
    • 텍스트로 입 출력 되는 환경
  • GUI (Graphical User Interface)
    • 그래픽 환경

디렉토리와 폴더의 차이

TUI 환경에서는 디렉토리라고 부르고, GUI 환경에선 폴더라고 부른다.

사용자

UNIX에서는 사용자는 devkuma 라든지 kimkc 등의 사용자명으로 식별된다. 사용자 정보는 /etc/passwd라는 파일에 기록된다.

그룹

사용자는 여러 그룹에 속할 수 있다. 예를 들어, devkuma와 kimkc의 두 사람이 adm이라는 그룹에 소속되어 있다고 한다. 그룹 정보는 /etc/groups라는 파일에 기록된다.

권한

rwxr-xr-x와 같은 9자는 권한을 나타낸다.

쉘(Shell)

Windows 명령 프롬프트(이전 이름: MS-DOS 프롬프트)에 해당하는 UNIX의 명령을 셸이라고 한다. 텍스트 모드에서 명령을 입력하면 결과도 텍스트로 표시된다.

프롬프트(Prompt) 정의

명령어를 입력 받아 실행될 수 있는 대기 상태이다.

prompt 구조

Windows (MS-DOS)

  드라이버명//경로>
  C://windows>

Linux (Bash Shell)

구분자 의미
root 로그인한 사용자 계정 명
localhost 리눅스 시스템의 호스트 명
~ 현재 작업 디렉토리 위치
# 관리자 계정(#), 일반 계정($)
[root@localhost ~]#
[devkuma@localhost ~]$

환경 변수

프로그램간에 정보를 교환할 때 참조할 수 있는 특수한 변수를 환경 변수라고 한다. Windows의 “AUTOEXEC.BAT"에서 지정한 “PATH"와 같다. CGI는 환경 변수를 통해 WWW 서버와 CGI 스크립트간에 많은 정보를 교환합니다. 주요 환경 변수는 다음과 같다.

환경 변수 의미
PATH 명령 검색 경로. 예를 들어, PATH=/bin:/usr/bin일 때 ls 명령을 실행하면 쉘은 /bin/ls, /usr/bin/ls를 순서대로 찾아서 먼저 발견된 명령을 실행한다. 반대로 PATH로 설정되지 않은 명령은 /bin/ls와 절대 경로 이름으로 지정해야 한다.
TZ 시간대. 해당 지역의 시간대를 지정합니다. 예를 들어 한국의 경우는 TZ=KST-9(최근에는 TZ=Asia/Seoul)로 지정해 둔다. 그렇지 않으면 시스템에 따라 시간이 9시간 벗어날 수 있다.

환경 변수의 값을 알기 위해서는, 쉘의 경우는 printenv(printenv 를 사용할 수 없는 때는 set) 커멘드, perl 의 경우는 $ENV{‘환경 변수명’} 을 이용한다.

UNIX와 Windows의 차이

UNIX Windows
드라이브 개념 없다 있다
디렉토리 구분 기호 / \
파일 목록 ls dir
파일 복사 cp copy
파일 삭제 rm del
파일 이동 mv move
파일 이름 바꾸기 mv ren
디렉토리 생성 mkdir mkdir
디렉토리 삭제 rmdir rmdir
디렉토리 이동 cd cd
일반적인 도움말 보기 man command command /?
환경 변수 표시 set/printenv set
파일 이름 길이 256자 255자
파일명의 대소문자 구별한다 구별하지 않는다.
실행 파일 퍼미션으로 의해 확장자에 의해
텍스트 파일의 개행 문자 <LF> <CR><LF>
한자 코드 UTF-8(옛날에는 EUC) UTF-8

2.1.1 - Linux 명령어 | Linux 소개 | Linux 기본 명령어

파일의 단어/줄 등의 총 개수 조회

wc [option] [보고 싶은 파일 위치/이름]

word counts : 파일의 단어/줄 등의 총 개수를 알려준다.

option :

  • -l
  • -w 단어

리눅스 명령어의 절대경로 조회

which [리눅스 명령어]

which : 리눅스 명령어의 절대경로를 보여준다.

파일에서 특정 패턴 조회

grep [패턴] [패턴이 있는지 확인할 파일 이름]

grep : 파일에서 특정 패턴이 어디에 있는지 알려준다.

패턴 : ex. “dump”

현재 사용자 변경

su [ID]

substitude user : 사용하고 있는 User를 변경한다. (ID 변경)

입력/출력 지정

> or >> [입/출력 장치]

redirection : 입력/출력 장치를 직접 지정해준다.

  1. cat test.txt > 1.txt (test.txt 파일을 cat한 것들을 1.txt에 덮어쓴다.)
  2. cat test.txt » 1.txt (test.txt 파일을 cat한 것들을 1.txt에 이어쓴다.)
  3. cat test.txt 라는 명령어는 cat test.txt > 이다. > 뒤에 아무것도 없으면 화면에 출력한다.

리눅스 명령어 차례대로 실행

| (backspace키 옆에 있는 문자)

pipeline : 리눅스 명령어들을 이어준다. (여러 명령어를 사용할 때 쓴다.)

예를들면

cat test.txt | head -1

2.1.2 - Linux 명령어 | Linux 소개 | Linux 디렉토리

드라이브

Windows에서는 “C:”, “D:“와 같은 드라이브라는 개념이 있지만 Unix/Linux에는 없다. 추가 하드 디스크, CD-ROM 등은 /dev/hda/dev/cdrom과 같은 경로 이름으로 액세스된다.

디렉토리

Windows에서 말하는 “폴더"와 거의 같은 의미이다. 디렉토리(폴더)의 구분은, Windows에서는 \Program Files\Microsoft Office\... 등 백슬래시(\)를 사용하지만, Unix/Linux에서는 /home/devkuma/public_html/index.html 등 슬래시(/) 를 사용한다.

home
└── devakuma
    └── pubilc_html
        ├── image
        │   ├── aaa.gif
        │   └── bbb.gif
        └── js
            ├── xxx.js
            └── zzz.js

루트 디렉토리

디렉토리 계층 구조의 최상위 디렉토리를 루트 디렉토리라고 한다. 첫 번째 슬래시(/)는 루트 디렉토리를 나타낸다.

/

홈 디렉토리

Unix/Linux에서는 각 사용자에게 별도의 디렉토리가 할당된다. 이를 “홈 디렉토리"라고 한다. Linux에서는 “/home/{사용자 이름}”, Mac OS X에서는 “/Users/{사용자 이름}”, 오래된 Unix계 OS에서는 “/usr/{사용자 이름}” 등이 주로 사용되지만, 다른 디렉토리를 사용할 수도 있다.

/home/devakuma

현재 디렉토리

현재 자신이 있는 디렉토리를 현재 디렉토리라고 한다. pwd 명령을 실행하면 현재 어떤 디렉토리에 있는지, 현재 디렉토리를 알 수 있다. 예를 들어, public_html 디렉토리에 있는 상태에서 pwd 명령을 실행하면 다음과 같이 표시도된다.

/home/devakuma/public_html

상위 디렉토리

루트 디렉토리를 제외한 모든 디렉토리에는 상위 디렉토리가 있다. 상위 디렉토리는 ..로 표시된다. ../xxx.html은 현재 현재 디렉토리의 상위 디렉토리에 있는 xxx.html이다. /home/users/../users/devkuma/home/users/devkuma 와 같은 의미가 된다.

경로명

어느 디렉토리안에 있는 파일의 위치를 ​​/home/foo/index.html (와)과 같이 나타낸 것을 패스명이라고 부른다. 이는 home 디렉토리내의, foo 디렉토리안의, index.html 라고 하는 파일을 나타낸다.

절대 경로명

경로명이 슬래시(/)로 시작되는 경우는 루트 디렉토리로부터의 상대 위치를 나타낸다. 이는 절대 패스명이나, 풀 패스명이라고 부른다.

URL의 설명과 약간 다를 수 있다. 예를 들어, /home/devkuma/public_html/index.htm이라는 절대 경로 이름이 URL에서 /index.htm이라는 가상 경로 이름에 매핑된다.

또, BIGLOBE와 같이, FTP로 로그인할 때와, CGI 스크립트가 동작할 때의 루트 디렉토리가 다른 경우가 있으므로 주의가 필요하다.

상대 경로 이름

경로명이 슬래시(/) 이외로 시작되는 경우는 현재 디렉토리로부터의 상대 위치를 나타낸다. 이를 상대 경로 이름이라고 한다.

예를 들어, 현재 디렉토리가 /home/users 일 때, devkuma/index.html을 작성하면 /home/users/devkuma/index.html이 표시된다.

가상 경로 이름

이것은 UNIX 용어보다는 WWW 용어인데, http://서버명/패스명/패스명의 부분을 가상 패스명이라고 부른다. 앞에서 설명한 것처럼 절대 경로 이름과 다르다.

주요 디렉토리

/

리눅스 상에 존재하는 모든 파일과 디렉토리의 최상위에 위치하는 최상위 디렉토리이다.
시스템의 근본이 되는 가장 중요한 디렉토리이다.
문자열 가장 앞의 /는 최상위를 나타내고, 그 이후의 /는 디렉토리 구분자이다. 문자열 마지막의 /는 보통 생략한다.

/boot

리눅스 커널의 메모리 이미지와 부팅 과정에서 필요한 정보 파일들이 있다.

/bin

리눅스의 기본적인 명령어 실행파일이 들어있다.

/root

슈퍼유저 root의 홈 디렉토리이다.

/home

관리자 이외의 사용자의 홈 디렉토리가 생성되는 디렉토리이다.
일반 사용자 계정 생성 시 기본적으로 이 디렉토리 하위에 생성한다.

/etc

시스템이나 사용자 관리를 위한 자료 파일과 관리자용 명령들을 가지고 있다.
시스템 설정 파일, 계정 정보들이 들어있고, backup 1순위 디렉토리이다.

/dev

장치 파일이라고 하는 파일시스템과 하드웨어 간의 인터페이스를 담당하는 파일이 있다.
플로피 디스크, 하드 디스크, CD-ROM 등의 각종 장치 파일들이 들어있다.

/lib

각종 언어를 위한 라이브러리를 가진다.
시스템 공유 라이브러리 디렉토리로, 프로그램에 필요한 라이브러리 파일이 존재한다.

/mnt

Remote Device를 이용하기 위한 디렉토리이다.
시스템에서 사용할 각 장치들의 마운트 포인터가 존재한다.
마운트를 하지 않은 상태에서는 아무런 내용이 나타나지 않지만 특정 디바이스로 마운트 하면 그 내용이 표시된다.

/media

Local Device를 이용하기 위한 디렉토리이다.

/sbin

시스템 운영 및 관리를 위한 명령 파일들이 있고 관리자 만이 사용할 수 있다. 부팅 과정에 필요한 명령들은 여기에 있고 정상 동작 상태에서 필요한 크기가 큰 명령들은 /user/sbin에 있다.

/user

리눅스가 구동하는데 필요한 대부분의 파일이 담겨있고 각 계정의 사용자들이 설치하는 패키지들이 존재한다.
용량이 큰 파일들 존재한다.

/proc

커널과 프로세스 정보를 얻을 수 있는 가상 파일 시스템으로 메모리상에 저장되어 있다.
프로세스의 정보를 나타내는 디렉토리로 ps 명령어로 프로세스 상태를 확인할 경우 이 디렉토리에 포함된 내용을 보여줌

/proc/cpuinfo

cpu에 대한 정보가 들어있다.

/proc/devices

디바이스 드라이버에 대한 정보가 들어있다.

/proc/kmsg

커널로부터 출력하는 메시지가 들어있다.

/proc/meminfp

실제 메모리와 가상 메모리에 대한 정보가 들어있다.

/proc/net

네트워크에 대한 정보가 들어있다.

/tmp

잠시 사용되는 임시 파일들이 저장되는 곳으로 PHP에서 파일 업로드 시 우선 저장되는 곳이고 세션 정보 등이 임시로 보관되는 디렉토리이다.

/var

가변 파일 디렉토리로 시스템 운영 중에 생성되거나 변경되는 파일이 존재한다.
메일, 스풀, 네임서버, 기타 보안사항에 관련되는 내용들이 기록된다.

/var/log

로그파일이 존재하는 디렉토리이다.

  • /var/log/cron : 주기 예약 작업 로그
  • /var/log/maillog : 메일 로그
  • /var/log/messages : 시스템 메시지 로그
  • /var/log/secure : 접속 및 인증 관련 로그 (★)
  • /var/log/spooler : 프린터 연결 로그
  • /var/log/dmesg : 시스템 장치 및 파일 시스템 부팅 메시지 로그
  • /var/log/boot.log : 부팅 시 시스템 장치 및 데몬 실행 상태 확인 로그

/var/spool/mail

주고받는 메일이 저장되는 디렉토리이다.

2.2 - Linux 명령어 | 파일 관리

리눅스에서의 파일 관리 명령에 대해서 설명한다.

2.2.1 - Linux 명령어 | 파일 관리 | ls 파일 목록 조회

ls 명령어

현재 위치 혹은 원하는 위치에 있는 모든 파일 목록을 보여준다.
ls는 list의 약자이다.

문법

ls (옵션) (경로:생략하면 현재 위치)

매개 변수 설명

  • -l : 자세히 보기
  • -a : 모든 파일 보기 (숨김파일까지)
  • -r : 역순으로 보기
  • -R : 하위 디렉토리 끝까지 보기
  • -t : 시간순으로 보기
  • -lrt : 위에서 아래로 시간순으로 자세히 보기

NOTE : 리눅스 대소문자 리눅스는 대소문자를 구분하므로 -r이 아닌 -R로 써야 한다.

ls 명령어 사용 예제

예제 1)

현재 디렉토리(pwd를 입력했을때 나온 위치)의 목록 보여준다.

ls

예제 2)

/home/devkuma 디렉토리 내용을 자세히 보여준다.

ls -l /home/devkuma
[devkuma@localhost ~]$ ls -l /home/devkuma
합계 4
drwxr-x---. 6 root    root     49  6월  6 08:06 data
-rwx------. 1 devkuma devkuma 198  6월  1 11:20 deploy

NOTE : 파일 유형 목록 내용에서 앞에 표시되는 문자열(예:drwxr-x—)의 의미는 아래와 같다.

  1. d로 시작하는것 = 디렉토리
  2. -로 시작하는 것 = 파일
  3. l로 시작하는 것 = 링크 파일(바로 가기)

예제 3)

/etc 디렉토리의 숨김 파일 포함해서 보여준다.

ls -a /etc

NOTE : 숨김 파일 (.)으로 시작되는 파일은 숨김파일이다. (예: .ssh)

예제 5)

/etc의 하위 디렉토리 끝까지 보여준다.

ls -R /etc

예제 6)

/etc의 숨김 파일 포함해서, 하위 디렉토리 끝까지 자세히 보여준다.

ls -alR /etc

NOTE : 명령어 옵션 순서 명령어의 옵션은 조합이 가능하다. 순서는 상관없다.

2.2.2 - Linux 명령어 | 파일 관리 | cd 다른 디렉토리로 이동

cd 명령어

다른 디렉토리로 이동한다.
cd는 change directory의 약자이다.

문법

cd [이동할 디렉토리의 위치 (상대경로 or 절대경로)]

cd 명령어 사용 예제

예제 1)

로그인된 사용자의 홈 디렉토리로 이동한다.

cd

예제 2)

/home 디렉토리로 이동한다.

cd /home

예제 3)

현재 디렉토리로 이동한다.

- cd . 

예제 4)

상위 디렉토리로 이동한다.

cd .. 

예제 1)

로그인된 사용자의 홈 디렉토리로 이동한다.

cd ~

예제 5)

지정된 계정의 홈 디렉토리로 이동한다.

cd ~계정명

NOTE : 홈 디렉토리

  • 계정 전용 공간
  • 계정 접속 위치

2.2.3 - Linux 명령어 | 파일 관리 | pwd 현재 경로 확인

pwd 명령어

현재 위치의 절대경로를 조회한다.
pwd는 print working directory의 약자이다.

사용법

pwd

예제

[devkuma@localhost ~]$ pwd
/home/devkuma

2.2.4 - Linux 명령어 | 파일 관리 | mkdir 디렉토리 생성

mkdir 명령어

디렉토리 생성한다.
mkdir는 make directory의 약자이다.

사용법

mkdir [생성할 디렉토리 이름]

option

  • -p : 상위 디렉토리 까지 생성한다.

mkdir 명령어 사용예제

예제 1)

최상위 디렉토리에 test 디렉토리를 생성한다.

mkdir /test

이 명령어는 root 권한이 없다면 생성되지 않는다.

[devkuma@localhost ~]$ mkdir /test
mkdir: /test: Permission denied

최상위 디렉토리에 디렉토리를 생성하려면 root 권한이 필요하다.

예제 2)

현재 디렉토리에서 a 디렉토리 안에 b라는 디렉토리 생성한다.

mkdir a/b

이 명령어는 현재 디렉토리에서 a디렉토리가 존재하지 않는다면 생성되지 않는다.

[devkuma@localhost ~]$ mkdir a/b
mkdir: a: No such file or directory

여러 경로(a/b) 존재시에 항상 마지막 경로(b)가 타겟이 된다.
위의 명령어는 a디렉토리와 그 안에 b디렉토리를 생성하라는 것이 아니라, a디렉토리가 존재할 경우 그 안에 b라는 디렉토리를 생성하라는 뜻이다.

예제 3)

현재 디렉토리에서 a 디렉토리를 생성한뒤 그안에 b라는 디렉토리 생성한다.

mkdir -p a/b

2.2.5 - Linux 명령어 | 파일 관리 | rmdir 디렉토리 삭제

rmdir 명령어

비어있는 디렉토리 삭제한다.
rmdir는 remove directory의 약자이다.

문법

rmdir (옵션) [삭제할 디렉토리 이름]

option:

  • -p : 상위 디렉토리도 삭제

rmdir 명령어 사용 예제

예제 1)

rmdir aaa

빈 디렉토리 aaa 삭제한다.

예제 2)

rmdir -p /a/b/c

빈 디렉토리 a, b, c,를 한 번에 삭제한다.
파일이 존재할 경우 서브 디렉토리는 그대로 존재한다.

2.2.6 - Linux 명령어 | 파일 관리 | rm 파일/디렉토리 삭제

rm 명령어

파일 및 디렉토리 삭제한다. rm은 remove의 약자이다.

사용법

rm (옵션) [삭제할 파일 명 및 디렉토리 명]

option :

  • -r : 일반 파일은 그냥 지우고 디렉토리면 디렉토리를 포함한 하위 경로와 파일 모두를 지운다.
  • -i : 지울 것인지 확인을 한다 (y,n)
  • -f : 물어보지 않고 지운다.
  • -rf : 삭제 여부를 묻지 않으며 하부 파일이 있는 디렉토리까지 삭제한다.

NOTE

  • 주로 rm -rf 옵션을 사용한다.

rm 명령어 사용 예제

예제1) 파일 삭제

test 파일을 삭제한다.

rm test

test 파일 삭제시 정말로 지울것인지 질의를 한다.

rm -i test 

test 파일 삭제시 강제 실행한다.

rm -f test 

예제1) 디렉토리 삭제

test-dir 디렉토리를 삭제한다.

rm -r testdir

testdir 디렉토리의 안에 파일이 있던 없던 무시하고 무조건 지운다.

rm -rf testdir

2.2.7 - Linux 명령어 | 파일 관리 | cp 파일/디렉토리 복사

cp 명령어

파일/디렉토리을 복사한다. cp는 copy의 약자이다.

사용법

cp (옵션) [대상 파일의 위치/이름(여러 개 가능)] [복사하고 싶은 위치/이름]

option:

  • -r : 하위 디렉토리와 파일 전체를 복사
  • -p : 소유주, 그룹, 권한, 시간 정보를 보존하여 복사

NOTE

  • 복사하고 싶은 위치에 같은 이름의 파일명이 존재 할 경우 덮어쓰기(y/n?, y=yes)를 묻는다.

CP 명령어 사용 예제

예제 1)

inittab 파일과 passwd 파일과 grub.conf 파일을 /backup 디렉토리에 복사한다.

cp /etc/inittab /etc/passwd /boot/grub/grub.conf /backup

예제 2)

skel 폴더(하위 디렉토리 및 파일 전체 포함)를 /backup 안에 복사한다.

cp -r /etc/skel /backup

예제 3)

passwd 파일을 /backup 디렉토리로 보존 복사한다.

cp -p /etc/passwd /backup

예제 4)

inittab 파일을 init로 이름 변경 복사한다.

cp /etc/inittab /backup/init

2.2.8 - Linux 명령어 | 파일 관리 | mv 파일/디렉토리 이동

mv 명령어

파일/디렉토리를 이동시키거나 이름을 바꿔준다. mv는 move의 약자이다.

  1. 이동하고 싶은 위치에 같은 이름의 파일명이 존재 하지 않을 경우 이동
  2. 이동하고 싶은 위치에 같은 이름의 파일명이 존재 할 경우 이름 변경

사용법

mv  [대상 파일의 위치/이름] [이동하고 싶은 위치/이름]

mv 명령어 사용 예제

예제1)

test1 파일을 /backup 으로 이동한다.

mv /test/test1 /backup

예제2)

passwd 파일을 pw로 이름 변경한다.

mv /backup/passwd /backup/pw

2.2.9 - Linux 명령어 | 파일 관리 | ln 링크 파일/디렉토리 만들기

ln 명령어

링크 파일(윈도우의 바로가기)을 생성한다. 링크의 종류로는 소프트링크/하드링크가 있다. ln은 link 약자이다.

문법

$ ln (옵션) [파일명] [링크 파일명]

매개 변수 설명

  • -s : 조사중
  • -sf : 소프트 링크 (링크파일을 실행하면 링크된 경로를 실행)

NOTE ; 숨겨진 이름앞에 . 이 붙어서 숨겨져 있는 디렉토리 안에 있는 디렉토리를 자주 열어볼 필요가 있을 때 바로가기를 만들어 두면 편하다.

ln 명령어 사용 예제

예제

$ln -s TestFile Test
$man ln

2.2.10 - Linux 명령어 | 파일 관리 | head 파일 내용 윗줄부터 출력

head 명령어

파일 내용을 위에서 부터 기본 10라인 출력한다.

사용법

head (-숫자) [파일명]

option :

  • -1 확인싶은 라인 수를 입력한다.

head 명령어 사용 예제

예제1)

/etc/passwd 파일 내용을 윗라인부터 5라인 출력한다.

-> head -5 /etc/passwd

예제2)

/etc/passwd 파일 내용을 윗줄부터 10라인 출력하고, 좌측에 라인 번호를 출력한다.

head /etc/passwd | cat -n

2.2.11 - Linux 명령어 | 파일 관리 | tail 파일 내용 제일 아래줄부터 출력

tail 명령어

파일의 내용을 제일 아래 라인부터 화면에 출력한다.
파일 내용을 아래에서 부터 기본 10라인 출력한다.

사용법

tail (옵션) [보고 싶은 파일 위치/이름]

option :

  • -1 확인싶은 라인 수를 입력한다.

tail 명령어 사용 예제

예제 1)

/etc/passwd 파일 내용을 아래줄부터 5라인 출력한다.

tail -5 /etc/passwd

예제 2)

/etc/passwd 파일 내용을 아래줄부터 10라인 출력하고, 좌측에 라인 번호를 출력한다.

tail /etc/passwd | cat -n

2.2.12 - Linux 명령어 | 파일 관리 | cat 파일 내용 출력

cat 명령어

파일 내용 출력한다.
입/출력 리다이렉션(>, >>)을 같이 사용해서 파일 생성 및 파일 내용 입력한다.
cat는 catch의 약자이다.

문법

cat [옵션] [파일명]

cat 명령어 사용 예제

예제 1)

/etc/passwd 파일 내용 출력한다.

cat /etc/passwd

예제 2)

좌측에 줄 번호를 출력하여 /etc/passwd 파일 내용 출력한다.

cat -n /etc/passwd

NOTE : #는 주석을 의미한다.

예제 3)

cat > [파일명]
  [파일 내용 입력] (ctrl + d를 누르면 입력 완료)

파일이 있으면 내용을 덮어쓰고 없으면 생성한뒤 내용을 입력한다.

예제 4)

cat >> [파일명]
  [추가할 내용 입력]

파일이 있으면 내용을 추가하고 없으면 생성한뒤 내용을 입력한다.

NOTE

  • > (쓰기) : 1. 파일생성 , 2. 덮어쓰기
  • >> (추가) : 1. 파일생성 , 2. 내용 추가

2.2.13 - Linux 명령어 | 파일 관리 | find 파일/디렉토리 검색

find 명령어

파일및 디렉토리 검색한다.

find [경로] [-name] [파일 및 디렉토리 명] [-type d/f]

예제 1)

find /etc/ -name config           

/etc안에서 이름이 config인 파일 및 디렉토리 검색

예제 2)

find / -name home -type d

최상위에서 이름이 home이고 타입이 디렉토리인 것만 검색한다.

예제 3)

find / -name passwd -type f

최상위에서 이름이 passwd이고 타입이 파일인 것만 검색한다.

find 고급 명령어

예제 1)

-find [경로] [-atime] [+n] (-n일 경우 n일 이내)

파일에 접근한지 n일 이상 검색한다.

예제 2)

-find [경로] [-ctime] [+n] (-n일 경우 n일 이내)

파일을 생성한지 n일 이상 검색한다.

예제 3)

-find [경로] [-mtime] [+n] (-n일 경우 n일 이내)

파일을 변경한지 n일 이상 검색한다.

예제 4)

-find [경로] [-amin] [+n] (-n일 경우 n분 이내)

파일에 접근한지 n분 이상 검색한다.

예제 5)

-find [경로] [-cmin] [+n] (-n일 경우 n분 이내)

파일을 생성한지 n분 이상 검색한다.

예제 6)

find [경로] [-mmin] [+n] (-n일 경우 n분 이내)

파일을 변경한지 n분 이상 검색한다.

예제 7)

-find [경로] [-newer] [파일 및 디렉토리 명]

[파일 및 디렉토리 명]이 생성후 수정된 모든 파일 및 디렉토리 검색한다.

예제 8)

여러 명령어를 한줄에 줄 수도 있다.

find / -name a
find / -name b
find / -name a -o -name  b   ## 이렇게 한줄로 줄여서 쓸수도 있음.

2.2.14 - Linux 명령어 | 파일 관리 | touch 빈 파일 생성

touch 명령어

크기가 0byte인 파일 생성한다.

사용법

touch [파일명]

touch 명령어 사용 예제

예제 1)

/backup에 1이라는 파일 생성한다.

touch /backup/1

예제 2)

/backup에 2와 3이라 파일 생성, /test에 1이라는 파일 생성한다.

touch /backup/2 3 /test 1

2.2.15 - Linux 명령어 | 파일 관리 | chmod 파일/디렉토리 권한 변경

리눅스/UNIX 권한

리눅스/UNIX 권한은 10자리로 표현된다.

예를들면, ls -lrt 명령어로 디렉토리 파일을 확인해 보면 다음과 같이 볼 수 있다.

% ls -lrt
total 8
-rwxrw-r--   1 kimkc  staff   37  5 13 08:40 README
drwxr-xr-x   8 kimkc  staff  256  5 13 08:40 java--tutorial

10자리의 의미를 알려면 “1자리/3자리/3자리/3자리"로 나누어서 보면 된다.

  • 디렉토리(1자리)
  • 소유자 권한(2~4자리)
  • 그룹 권한(5~7자리)
  • 전체 권한(8~10자리)

우리가 확인해야 할 볼 권한 부분은 앞에 drwx로 되어 있는 부분이다.

  • r : 읽기권한
  • w : 쓰기권한
  • x : 실행권한

다시 예제를 보고 확인해 보도록 하자.

  • 첫번째자리 d(디렉토리), -(파일)을 뜻한다. 즉, 예제에서 1개는 디렉토리이고 1개는 파일이다.
  • 두번째자리 3개(소유자 권한) rwx : 소유자 권한이 읽기/쓰기/실행 권한이 있다는 것을 뜻한다.
  • 세번째자리 3개(그룹 권한) rw- : 그룹 권한은 읽기/쓰기 권한만 있다는 것을 뜻한다.
  • 네번째자리 3개(전체 권한) --r : 전체권한은 쓰기 권한만 있다는 것을 뜻한다.

chmod 명령어

파일의 권한을 변경한다. chmod는 change mode의 약자이다.

r/w/x 권한을 각각 숫자로 표현하면 4/2/1 이다. (단순 덧셈으로 각 부분의 권한을 주게 된다.)

  • 7/7/7 => 소유자 권한/그룹 권한/전체 권한. (7이라는 숫자는 단순 덧셈 4+2+1 이다.)

위에 예제로 예를 들면 chmod 777 README 실행을 하게 되면 , README 파일 권한이 -rwxrwxrwx(777)으로 변경되게 된다.

사용법

chmod [option (ex.744)] [변경할 파일 위치/이름]
  1. 권한은 숫자로 표현되며 읽기(4), 쓰기(2), 실행(1)으로 나뉜다.
  2. 읽고쓰기=4+2=6, 읽고실행=4+1=5, 쓰고실행=2+1=3, 읽고쓰고실행=4+2+1=7
  3. 권한은 총 3구역으로 설정되며, 나 / 내가 속한 그룹 / 다른 그룹 으로 나뉜다.
  4. 나는 읽고 / 내가 속한 그룹은 쓰고 / 다른 그룹은 실행 = 421

2.2.16 - Linux 명령어 | 파일 관리 | chown 파일/디렉토리 소유권 변경

소유권 확인

먼저 소유권을 확인하기 위해서는 아래 명령어로 확인이 가능하다.

ls -al 

위 명령어를 입력하면 아래와 같은 형태로 결과물이 나온다.

-rw-r--r--   1 kimkc  staff      36864  5 10  2015 Currency.db

여기서 소유권자가 kimkc이고, 그룹 식별자가 staff이다.

파일 소유권 변경

root 권한에에서 아래 명령어를 실행한다.

명령어

chown {소유권자}:{그룹식별자} {소유권을 변경하고 싶은 파일명}

test.sh 파일명의 소유권자를 aaa로 하고, 그룹식별자를 bbb로 변경하는 명령어는 아래와 같다.

예제

chown aaa:bbb test.sh

디렉토리 소유권 변경

root 권한에에서 아래 명령어를 실행한다.

명령어

chown {소유권자}:{그룹식별자} {소유권을 변경하고 싶은 디렉토리명}

/home/test 디렉토리만 소유권자를 aaa로 하고, 그룹식별자를 bbb로 변경하는 명령어는 아래와 같다.

예제

chown aaa:bbb /home/test

위 명령어로 디렉토리 소유권은 변경하게 되면 /home/test 디렉토리만 소유권이 변경되고, 이하 디렉토리는 소유권이 변경되지 않는다.

하위 디렉토리까지 모두 소유권 변경

root 권한에에서 아래 명령어를 실행한다.

명령어

chown -R {소유권자}:{그룹식별자} {소유권을 변경하고 싶은 디렉토리명}

/home/test 디렉토리와 이하 모든 디렉토리 및 파일들의 소유권자를 aaa로 하고, 그룹식별자를 bbb로 변경하는 명령어는 아래와 같다.

예제

chown -R aaa:bbb /home/test

위 명령어로 디렉토리 소유권은 변경하게 되면 /home/test 디렉토리는 물론 이하 모든 디렉토리 소유권이 변경된다.

2.2.17 - Linux 명령어 | 파일 관리 | df 디스크 용량을 파티션별

df 명령어

현재 디스크 용량을 파티션별로 확인할 수 있다.

사용법

df [옵션] [파일시스템]

option

  • -a, –all : 모든 파일 시스템을 대상으로 점검한다. 더미 파일 시스템으로 크기가 0인 것도 모두 보여준다. 어떤 시스템에서는 ignore 또는 auto 파일 시스템이 초기값으로 생략되는 경우가 있는데, 이 때 이 옵션을 사용한다.
  • -i, –inodes : 파티션별로 디스크사용량 점검 시에 블록 사용 정보 대신에 inode 사용 정보를 표시한다. inode란 특별한 종류의 디스크 블록인데, 이것은 파일이름, 소유주, 권한, 시간정보, 디스크에서의 위치 등에 대한 정보를 담고 있다.
  • -k, –kilobytes : 표시하는 숫자들의 단위를 512바이트 블럭 단위 대신 1KB 단위로 표시한다.
  • -h, –human : 디스크사용량을 파티션별로 확인할 때 표시되는 용량을 알기 쉬운 용량단위(byte, Kbyte, Mbyte, Gbyte 등)로 표시한다.
  • -P, –portability : POSIX에서 사용되는 형태로 보여준다. 이 옵션은 한 줄에 하나의 파일 시스템 정보만 보여준다는 것을 제외하면 원래 출력 양식과 같다. 만약 마운트 장치 이름이 20문자 이상이면 줄이 나누어지는데 이런 경우는 생략되거나 축약된다.
  • -T, –print-type : 디스크사용량을 출력할 때 파일 시스템의 종류와 함께 표시한다. 특정 파일 시스템의 정보만 원할 때는 아래 두 옵션을 사용한다.
  • -t, –type=fstype : 특정 파일 시스템 종류만을 대상으로 디스크사용량을 조사한다.
  • -x, –exclude-type=fstype : 특정 파일 시스템의 종류를 제외한 디스크사용량을 조사한다.
  • -v : System V 용 df와 호환을 위한 옵션으로 무시한다.
  • –help : 도움말을 보여주고 마친다.
  • –version : 버전 정보를 보여주고 마친다.

유용한 옵션

  • -a / –all : 파일 크기가 0인 것 까지도
  • -l / –local : 지역 파일 시스템만
  • **-h / –human-readable **: 사람이 읽기 편한 단위로

df 명령어 사용 예제

예제

현재 서버의 디스크 사용량을 파티션별로 확인할 때에 용량을 Kbyte 단위로 표시하도록 함.

# df -k

현재 서버의 디스크 사용량을 파티션별로 확인할 때에 표시되는 용량을 알기쉬운 용량단위로 표시.

# df -h

디스크사용량을 출력할 때에 파일 시스템의 종류와 함께 출력

$ df -T

특정 파일 시스템의 종류만을 대상으로 디스크사용량을 조사

$ df -t ext4

사용 예

$ df
Filesystem    512-blocks      Used Available Capacity   iused    ifree %iused  Mounted on
/dev/disk0s2  1365813704 960084640 405217064    71% 120074578 50652133   70%   /
devfs                367       367         0   100%       636        0  100%   /dev
map -hosts             0         0         0   100%         0        0  100%   /net
map auto_home          0         0         0   100%         0        0  100%   /home
/dev/disk0s4    97652728  78802584  18850144    81%    130083  9473165    1%   /Volumes/BOOTCAMP

2.2.18 - Linux 명령어 | 파일 관리 | du 명령어 디스크 용량을 특정 디렉토리/파일

du 명령어

현재 디스크 용량을 특정 디렉토리, 파일 단위별로 확인할 수 있다.

사용법

$du (옵션) [파일명 혹은 폴더명]

option:

  • -s, --summarize : 하위 디렉토리는 합쳐서 전체 용량만 출력한다.
  • -a : –all. 모든 파일과 모든 하위 디렉토리도 출력한다.
  • -c : –total 마지막 줄에 합계를 출력한다.
  • -k : 출력 숫자의 단위를 1kbyte 로 지정한다.
  • -x : –one-file-system. 현재 파일시스템의 파일 사용양만 출력한다.

du 명령어 사용 예제

예제

$ du -ks /Users/devkuma/Sites/
119852 /Users/devkuma/Sites/

TIP

아래 명령어를 실행하면, 현재 디렉토리 내용을 쉽게 볼 수 있다.

$ du -ks *
$ du -ks -h *

참조

2.2.19 - Linux 명령어 | 파일 관리 | awk 패턴 탐색 처리

awk 명령어

패턴 탐색과 처리를 위한 명령어로 간단하게 파일에서 결과를 추려내고 가공하여 원하는 결과물을 만들어내는 명령어이다.

awk는 초기 개발자 Aho, Weinberger, Kernighan의 세 명의 성의 앞글자를 따서 붙여졌다. GNU 프로젝트에서 만들어진 텍스트 처리 프로그래밍 언어로 유닉스 계열의 OS에서 사용 가능하며, 텍스트 형태로 되어있는 입력 데이터를 행과 단어 별로 처리해 출력한다.

사용법

$ awk 'pattern' filename
$ awk '{action}'  filename
$ awk 'pattern' '{action}' filename

$ awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ...  ]

awk 명령어 사용 예제

예시1) 명령어로 출력되는 내용중에 원하는 필드만 표시

$ date
2018년 6월 24일 일요일 17시 16분 54초 KST
$ date | awk '{print $1}'
2018년

날짜를 표시하는 date에서 년도만 추출하여 표시한다.

예제2) 파일 내용을 추출하여 원하는 필드만 표시

$ cat sample.txt 
foo 한글 12 
dev 데브 24
kuma 쿠마 33
hello 헬로 55

kuma를 포함하는 라인 추출하여 표시

$ awk '/kuma/' sample.txt 
kuma 쿠마 33

공백 기준으로 두번째, 첫번째 필드만 표시

$ awk '{print $2, $1}' sample.txt
한글 foo
데브 dev
쿠마 kuma
헬로 hello

kuma를 포함하는 라인을 추출하여, 공백 기준으로 두번째, 첫번째 필드만 표시

$ awk '/kuma/{print $2, $1}' sample.txt
쿠마 kuma

예제3) 필드 구분자를 통한 표시

공백을 구분자로 하여 필드를 나눈 후 9번째 필드을 표시한다.

$ ls -al
total 59384
drwxr-xr-x  28 kimkc  staff       952  6 22 22:29 .
drwxr-xr-x+ 80 kimkc  staff      2720  6 24 16:57 ..
drwxr-xr-x  21 kimkc  staff       714  6 24 16:57 devkuma
drwxr-xr-x  18 kimkc  staff       612  1  2 23:12 tutorial
drwxr-xr-x  13 kimkc  staff       442  6 16 07:56 workspace
$ ls -al | awk -F " " '{print $9}'
.
..
devkuma
tutorial
workspace

2.2.20 - Linux 명령어 | 파일 관리 | sort 정렬

sort 명령어

sort는 명령어 출력 혹은 파일 내용을 정렬 하는데 사용한다.

사용법

sort [-옵션] [-o 저장될 파일명] 정렬할 파일명 [병합할 파일명]

option:

  • -b : 앞 공백 무시
  • -o : 저장할 파일 명시
  • -r : 역순으로 표시
  • -f : 대소문자 구분 하지 않음
  • -t : 필드 구분자 지정
  • -u : 중복행 제거
  • -m : 정렬 파일 병합
  • -n : 숫자만 비교

sort 명령어 예제

예제) 파일 내용 정렬

아래와 같이 숫자로만 이루워진 파일이 있다면

$ cat sample.txt 
3
1
5
9
7

명령어 sort [파일명]을 사용하여 출력을 정렬할 수 있다.

$ sort sample.txt 
1
3
5
7
9

예제) 열이 여러개 일때 정렬

아래와 같이 열이 두개라면

$ cat sample.txt 
3 f
1 b
5 a
9 c
7 e

명령어 sort +1 [파일명]을 사용하면 두번째 열 기준으로 정렬할 수 있다.

$ sort +1 sample.txt 
5 a
1 b
9 c
7 e
3 f

2.3 - Linux 명령어 | 압축 파일 관리

리눅스에서의 압축 명령어 tar, zip, gz, 7z에 대해서 설명한다.

2.3.1 - Linux 명령어 | 압축 파일 관리 | tar 압축하기, 압축풀기

tar.gz 압축하기

명령어

tar -czvf {압축 파일명}.tar.gz {압축할 파일1} {압축할 파일2}...

파일 압축하기

./test 라는 디렉토리에 a1.jpg, a2.jpg, a3.jpg 파일들을 images.tar.gz파일명으로 압축을 하는 명령어는 다음과 같다.

tar -czvf images.tar.gz ./test/a1.jpg ./test/a2.jpg ./test/a3.jpg

디렉토리 압축하기

./test 디렉토리 자체를 압축하는 명령어를 다음과 같다.

tar -czvf images.tar.gz ./test

특정 파일을 압축에서 제외하기

a1.jpg와 a2.jpg는 압축하고, a3.jpg는 압축에서 제외하고 싶은 때는 아래와 같이 명령어를 쓰면 된다.

tar -czvf --exclude=./test/a3.jpg images.tar.gz ./test

tar.gz 압축풀기

명령어

tar -xzvf {압축 파일명}.tar.gz 

images.tar.gz이라는 압축 파일을 푸는 명령어를 다음과 같다.

tar -xzvf images.tar.gz

tar 압축 풀기

tar 압축을 푸는 방법은 옵션에서 z만 빼주면 된다.

예를 들면, images.tar 이라는 압축 파일을 푸는 명령어는 아래와 같다.

tar -xvf images.tar

2.3.2 - Linux 명령어 | 압축 파일 관리 | zip, unzip 압축하기, 압축풀기

zip 압축하기

명령어

zip {압축 파일명}.zip {압축할 파일 혹은 디렉토리1} {압축할 파일 혹은 디렉토리2}...

파일 압축하기

특정 디렉토리에 모든 파일(./*)를 test.zip으로 압축한다.

zip test.zip ./*

파일 및 디렉토리 압축하기

현재 폴더에 여러 하위 폴더가 있는데, 그것도 다 같이 압축하기 위해서는 -r 이라는 옵션을 추가한다.
특정 디렉토리에 모든 파일 및 디렉토리(./*)를 test.zip으로 압축한다.

zip -r test.zip ./*

zip 압축풀기

zip파일을 압축을 푸는 명령어는 아래와 같다.

명령어

unzip {압축 파일명}.zip

파일 압축풀기

test.zip 파일의 압축을 푸는 명령어는 아래와 같다.

unzip test.zip

특정 디렉토리에 파일 압축풀기

test.zip 파일을 /home/devkuma 디렉토리에 압축을 푸는 명령어는 아래와 같다.

unzip test.zip -d /home/devkuma 

zip, unzip 설치하기

우분투에서 zip, unzip 설치

zip, unzip이 설치되지 않은 우분투에서는 아래 명령어로 설치할 수 있다.

명령어

sudo apt-get install zip unzip

2.3.3 - Linux 명령어 | 압축 파일 관리 | gz 압축하기, 압축풀기

gz 압축 하기

명령어

gzip {압축 파일명}

파일 압축하기

aaa.jpg를 gz으로 압축한다면 아래와 같은 명령어를 사용하면 된다.

gzip aaa.jpg 

수행 결과로 aaa.jpg는 없어지고, aaa.gz 압축 파일이 생성된다.

gz은 여러개의 파일을 하나로 압축하는 용도가 아니다.
여러개의 파일을 압축하시려면 tar, zip, 7z 압축을 사용하시길 바란다.

gz 압축 풀기

명령어

gzip -d {압축 파일명}.gz

gzip으로 압축을 푸는 옵션으로 -d 를 주면 된다. -d는 decompress의 줄임 표현이다.

gzip 설치하기

gzip은 리눅스에 기본으로 설치되어 있으나, 혹시 gzip 명령어를 찾을 수 없다고 나오면 아래 명령어로 설치하면 된다.

우분투에서 unzip 설치

 apt-get install gzip

2.3.4 - Linux 명령어 | 압축 파일 관리 | 7z 압축하기, 압축 풀기

7z 압축하기

명령어

7zr a {압축 파일명}.zip {압축할 파일 혹은 디렉토리1} {압축할 파일 혹은 디렉토리2}...

파일 압축하기

test1, test2, test3 파일을 라고 test.7z 파일명으로 압축을 하는 명령어는 다음과 같다.

7zr a test.7z test1 test2 test3 

7z 압축 풀기

명령어

7zr x {압축 파일명}.zip

test.7z 압축 파일을 푸는 명령어를 다음과 같다.

7zr x test.7z 

p7zip 설치하기

우분투(Ubuntu)에서 p7zip 설치하기

apt-get install p7zip

위 명령어로 설치가 안되면 아래 명령어로 검색하셔서 설치하시길 바란다.

apt-cache search 7z

페도라(Fedora)에서 p7zip 설치하기

yum install p7zip

위 명령어로 설치가 안되면 아래 명령어로 검색하셔서 설치하시길 바란다.

yum search 7z

2.4 - Linux 명령어 | 프로세스 관리

프로세스 관리

컴퓨터의 cpu에서 실행되는 모든 프로그램을 프로세스라고 한다. 프로세스가 잘못된 작업을 수행하거나 문제가 있으면 서버 전체 성능이 저하되어 상황을 주의 깊게 살펴야 한다.

부모 프로세스(PPID)

선행 프로세스라고도 부르며, 자식 프로세스를 발생시킬 수 있다.
부모 프로세스는 여러 개의 자식 프로세스를 실행하여 다수의 작은 작업들을 동시에 처리하도록 할 수 있다.

자식 프로세스

자식 프로세스는 부모 프로세스가 처리 중인 파일 등을 공유한다.
부모 프로세스에서 포크(fork)하여 생긴 프로세스이다.
프로그램에서는 부모프로세스의 복사로 부모와 교신하면서 프로세스를 진행하게된다.

2.4.1 - Linux 명령어 | 프로세스 관리 | ps 프로세스 목록

ps 명령어

현재 작동하는 프로세스의 목록을 출력한다.

사용법

ps (옵션)

option:

  • -e : 모든 프로세스 정보 출력
  • -f : 프로세스의 다양한 정보 출력
  • -a : 실행중인 전체 사용자의 모든 프로세스 출력
  • -u : 프로세스를 실행한 사용자 정보와 프로세스 시작 시간등 출력
  • -x : 제어 터미널을 갖지 않는 프로세스 출력

ps 명령어 사용예제

예제 1)

PID와 PPID를 확인할 수 있다.

ps -ef |grep *** (동작중인 프로세스) : 

예제 2)

USER, PID, %CPU, %MEM, RSS, TTY, STAT, START를 확인할 수 있다.

-> ps -aux |grep *** (동작된 프로세스) : 

NOTE

  • USER : 프로세스를 실행시킨 사용자
  • PID : 프로세스 ID
  • %CPU : 최근 1분간 프로세스가 사용한 CPU시간 백분율
  • %MEM : 최근 1분간 프로세스가 사용한 실제 메모리의 백분율
  • RSS : 현재 프로세스가 사용하고 있는 실제 메모리 크기
  • TTY : 프로세스를 제어하고 있는 터미널
  • STAT : 프로세스 상태 코드
  • START : 프로세스의 시작 시간

2.4.2 - Linux 명령어 | 프로세스 관리 | kill 프로세스 종료

kill 명령어

프로세스 종료시킨다.

사용법

kill (option) [PID:프로세스 아이디]

option(signal):

  • -1 : 재실행(HUP)
  • -9 : 강제종료(KILL)
  • -15 : 기다렸다 정상 종료(TERM)

kill 명령어 사용 예제

// 프로세스명이 tomcat인 항목의 PID 확인
$ ps -ef | grep tomcat
  501  2177     1   0 11:36PM ttys000    0:05.94 
	
... 생략 ...
	
// PID가 2177인 프로세스 종료
$ kill -9 2177

2.4.3 - Linux 명령어 | 프로세스 관리 | top 실시간 프로세스 모니터링

top 명령어

  • 실시간 프로세스 모니터링 프로그램
  • 기본적으로 3초마다 화면이 갱신되고 스페이스바를 누르면 바로 갱신된다.

사용법

top (option)

option:

  • -d [시간] : 화면 갱신 시간 설정
  • -i : idle 상태와 좀비 프로세스 무시

top 실행중 사용 가능 명령어

  • k : kill 명령
  • r : nice값 변경
  • l : top 맨 윗줄 항목 on/off
  • m : 메모리 항목 on/off
  • t : 프로세스와 CPU 항목 on/off
  • c : command line의 옵션 on/off
  • q : 프로그램 종료

2.4.4 - Linux 명령어 | 프로세스 관리 | uptime 현재 시간, 시스템 부팅 후 경과된 시간, 로그인 사용자, 시스템 부하율

uptime 명령어

uptime 명령어는 다음 정보를 보여준다.

  • 시스템 부팅 후 경과된 시간
  • 로그인 사용자 수
  • 최근 1, 5, 15분 간의 평균 시스템 부하율

사용 방법

다음 예제와 같이 명령어를 입력하면 된다.

% uptime
 8:37  up 22:25, 2 users, load averages: 2.24 5.27 3.76

위에 실행 결과는 다음과 같이 해석할 수 있다.

  • 현재 시간은 8:37 이다.
  • 부팅하고 22시간 48분이 경과되었다.
  • 2명의 사용자가 시스템에 로그인한 상태이다.
  • 시스템 부하율
    • 최근 1분간의 평균 시스템 부하율은 2.24.
    • 최근 5분간의 평균 시스템 부하율은 5.27.
    • 최근 15분간의 평균 시스템 부하율은 3.75.

2.5 - Linux 명령어 | 네트워크

리눅스에서의 네트워크 명령어에 대해서 설명한다.

2.5.1 - Linux 명령어 | 네트워크 | ifconfig 네트워크 정보 확인

ifconfig 명령어

네트워크 인터페이스 정보 확인한다.

사용법

ifconfig
ifconfig -a

비 활성화 장치 포함하여 모두 보기

ifconfig [interface] [up / down]

지정한 장치를 활성화 혹은 비 활성화할 때 사용

2.5.2 - Linux 명령어 | 네트워크 | netstat 네트워크 상태 확인

netstat 명령어

network statistics의 줄임말로 네트워크 인터페이스나 프로토콜 상에서의 통계를 보여주는 소프트웨어 혹은 도구이다. 대체로 네트워크의 상태 및 성능을 측정하고 네트워크 상의 문제점을 파악할 때 많이 쓰인다.

사용법

netstat [옵션] [| grep 포트 번호 or 서비스 명]

option:

  • -l (listen) : 연결 가능한 상태
  • -n (number port) : 포트 넘버
  • -t (tcp) : tcp
  • -u (udp) : udp
  • -p (Program name / PID) : 프로그램 이름 / PID. 어떤 프로세스에서 해당 통신을 사용하고 있는 지를 보여준다.
  • -a (all) : 모두. ESTABLISHED 뿐만 아닌 모든 State에 대한 소켓들의 정보를 보여준다

예시:

$ netstat
Active Internet connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)    
tcp4       0      0  192.168.0.1.62123      111.111.11.111.https   ESTABLISHED
  • Proto : 해당 통신이 사용하는 프로토콜을 나타낸다.
  • Recv-Q , Send-Q : 해당 통신이 사용할 때 소켓 사이즈 버퍼를 의미하며 Recv-Q의 경우 recv()를 - 통해 처리 받지 못한 데이터를 의미하며 Send-Q의 경우 send()를 통해 보냈지만 아직 완전하게 외부로 보내지지 않은 데이터의 크기를 의미한다.
  • Local Address, Foreign Address : 말 그대로 해당 통신에서 나가는 내 주소와 목적지에 해당하는 주소를 의미한다.
  • (state) : ESTABLISHED, LISTEN과 같은 상태를 나타낸다.

NOTE

포트

서버에 열린 문을 의미하며 숫자로 표현된다. IP를 타고 서버에 접속할 때 서버에 여러 포트가 있다.

TCP와 UDP

TCP: 속도↓, 상호 통신(신뢰성↑), 질의응답 o, stream
UDP: 속도↑, 일방 통신(신뢰성↓), 질의응답 x, datagram(dgram)

netstat 옵션은 주로 -lntup를 쓴다.

그 외에 -antup, -ltup, -atup 등을 쓴다.

/etc/services는 서비스 명 및 포트 정의 파일이고 포트 넘버를 확인 가능하다.

2.5.3 - Linux 명령어 | 네트워크 | ping 상대 호스트와 연결 가능 여부 확인

ping 명령어

상대 호스트와 연결 가능 여부 확인한다.

사용법

  • ping (option) [연결 가능 여부 IP 및 도메인]

option:

  • -c (count) : ping을 보낼 횟수
  • -i (interval) : ping을 보낼 간격
  • -s (size) : ping의 크기(최대 65507)
  • -f (fast) : 최대 속도

ping 명령어 사용 예제

아래 예제에서는 ping을 3번 보냈다.

[devkuma@localhost ~]$ ping -c 3 www.google.com
PING www.google.com (172.217.24.196): 56 data bytes
64 bytes from 172.217.24.196: icmp_seq=0 ttl=49 time=68.258 ms
64 bytes from 172.217.24.196: icmp_seq=1 ttl=49 time=70.593 ms
64 bytes from 172.217.24.196: icmp_seq=2 ttl=49 time=68.935 ms

--- www.google.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 68.258/69.262/70.593/0.981 ms

ping 트래픽

ping 기본 값: 8byte
ping 최댓값: 65515byte (65507 + 8)

ping 고급 설정

ping 막기(ICMF 막기)

$ echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

ping 허용(ICMF 허용)

$ echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all

2.5.4 - Linux 명령어 | 네트워크 | nslookup 도메인 정보 확인

nslookup 명령어

네임 서버에 질의하는 프로그램이다.
IP 주소를 아는데 도메인을 모르거나, 도메인은 아는데 IP 주소를 모를 때 알기 위해 쓴다.
DNS 정보와 연관된 도메인 정보를 확인할 수 있다.

사용법

nslookup [도메인 또는 아이피 입력]

nslookup 명령어 사용 예제

예제) 구글 조회

[devkuma@localhost ~]$ nslookup www.google.com
Server:    180.182.54.1
Address:  180.182.54.1#53

Non-authoritative answer:
Name: www.google.com
Address: 172.217.24.196

2.5.5 - Linux 명령어 | 네트워크 | scp 서버간 파일 복사

scp 명령어

리눅스에서 서버 간에 파일 복사에 사용되는 명령어이다.

명령어

scp {복사하려는 파일명}  {서버 사용자 아이디}@{서버 주소}:{서버의 복사 경로 위치}

참고

  • 서버의 아이디 및 비밀번호를 알고 있어야 한다.
  • 서버의 복사 경로 위치 앞에 : (콜론)을 꼭 붙어야 한다.
  • 서버의 복사 경로 위치는 기입한 서버의 아이디 계정의 쓰기 권한이 있어야 된다.

scp 명령어 사용 예제

예제) 파일 복사

로컬에 있는 test.txt 라는 파일을 서버에 /home/devkuma 의 디렉토리에 복사한다.

scp ./test.txt devkuma@192.168.0.10:/home/devkuma

예제) 디렉토리 복사

로컬에 있는 test_dir 디렉토리를 서버에 /home/devkuma 의 디렉토리에 복사한다.

scp -r ./test_dir devkuma@192.168.0.10:/home/devkuma

파일을 복사할 때와 다른 것은 옵션 -r이 추가했다는 것이다.

2.5.6 - Linux 명령어 | 네트워크 | wget 웹다운로드

wget 명령어

리눅스에서 wget는 웹 상에 존재하는 파일을 쉽게 다운로드 할 때 사용하는 명령어이다.

GNU Wget(간단히 Wget, 이전 이름: Geturl)는 웹 서버로부터 콘텐츠를 가져오는 컴퓨터 프로그램으로, GNU 프로젝트의 일부이다. 이 프로그램의 이름은 월드 와이드 웹과 get에서 가져온 것이다. HTTP, HTTPS, FTP 프로토콜을 통해 내려받기를 지원한다. - 위키백과

웹 파일 다운로드

wget --help 라고 치시면 매우 다양한 옵션을 제공한다.
웹 상에 있는 특정 파일을 다운로드 할 때 주로 사용하고 있다.

예를 들어, http://{URL}/file.tar.gz 이라는 주소에 파일이 위치하고 있다고 가정했을 때,

wget http://{URL}/file.tar.gz

위와 같이 명령어를 입력하면, 현재 폴더에 file.tar.gz이 다운로드 된다.

웹 파일을 특정 파일명으로 다운로드

특정 이름으로 저장하고 싶으면 영어 대문자으로 -O 옵션을 주시면 됩니다.
O는 Output의 O이다.

예를 들어, http://{URL}/file.tar.gz 을 ddd.tar.gz 으로 저장하고 싶다면

wget http://{URL}/file.tar.gz -O ddd.tar.gz 

위와 같이 입력하여 ddd.tar.gz으로 다운로드할 수 있다.

설치

Mac OS에 설치하기

% brew install wget

2.5.7 - Linux 명령어 | 네트워크 | curl 웹접속

curl 명령어

cURL(Client URL) 명령어는 command line의 data transfer tool 이다. 무료 오픈소스이며, 다양한 프로토콜을 지원한다.

다양한 프로토콜 지원

DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, Telnet, TFTP

사용법

  • curl (options…) [URL]

option:

  • -X : 사용할 방식 HTTP 메소드 선택한다.
  • -d, –data : request body 지정한다.
  • -d (file_name) : 텍스트 파일의 내용을 보낼 수 있다.
  • –data-urlencode: URL encode를 사용한다.
  • –data-binary: 바이너리 데이터를 전송할 때 사용한다.
  • -G : 전송할 사이트 url 및 ip 주소
  • -H : 헤더 정보를 전달하기
  • -i : 사이트의 Header 정보만 가져온다.
  • -I : 사이트의 Header와 바디 정보를 함께 가져온다.
  • -u : 사용자 정보를 표시한다.
  • -v: 자세한 정보를 표시한다.

curl 명령어 사용 예제

URL만 지정

$ curl www.devkuma.com

header 값 지정

$ curl -H "Content-Type: application/json" www.devkuma.com

http Method 지정

$ curl -X GET www.devkuma.com

2.6 - Linux 명령어 | 쉘 스크립트 (Shell Script)

셸 스크립트(shell script)는 셸이나 명령 줄 인터프리터에서 돌아가도록 작성되었거나 한 운영 체제를 위해 쓰인 스크립트이다

2.6.1 - Linux 명령어 | 쉘 스크립트 (Shell Script) | Vi Editor 명령어

Vi, VIM(Vi IMproved=향상된 VI)

빠른 편집 속도가 특징인 리눅스의 대표적인 에디터이다.
vi는 Visual의 약자이다

vi 시작 명령어

명령어 설명 예제
vi {파일명} 파일열기, 작성 vi test.txt
vi +{행번호} {파일명} 파일을 열고, 입력한 행으로 커서 이동 vi -100 test.txt
vi +/"{검색 문자열}" {파일명} “문자열”의 처음발생 단어부터 열기 vi -/“adc” test.txt
vi –r {파일명} 손상된 파일 회복 vi -r test.txt
view {파일명} 읽기 전용으로 열기기 view test.txt

수정 파일 열기

“vi {파일명}“명령어로 입력했을 때, 입력한 파일명이 실제 존재 한 경우 파일을 수정.

신규 파일 생성

“vi {파일명}“명령어로 입력했을 때, 입력한 파일명이 실제 존재 하지 않는 경우 파일을 생성.

vi 커서 이동

커서 설명
h (←) 왼쪽으로 커서 이동
j (↓) 아래로 커서 이동
k (↑) 위로 커서 이동
l (→) 오른쪽으로 커서 이동
w 오른쪽 한 단어의 끝 부분으로 커서 이동
e 오른쪽 한 단어의 앞 부분으로 커서 이동
b 왼쪽 한 단어의 앞 부분으로 커서 이동
Enter 한 행 아래로 커서 이동
Back space 한 문자 왼쪽으로 커서 이동
Space Bar 한 문자 오른쪽으로 커서 이동
^ 행의 맨 왼쪽으로 커서 이동
$ 행의 맨 오른쪽으로 커서 이동
H 화면의 맨 위로 이동
M 화면의 중간으로 이동
L 화면의 맨 아래로 이동
숫자G ‘숫자’ 만큼 지정한 줄로 커서 이동
Ctrl + i 한 화면 위로 이동
Ctrl + b 한 화면 아래로 이동
Ctrl + d 반 화면 위로 이동
Ctrl + u 반 화면 아래로 이동
Ctrl + e 한 줄씩 위로 이동
Ctrl + y 한 줄씩 아래로 이동

문자, 행 , 삽입 명령어

커서 설명
a 커서 오른쪽에 문자 삽입
A 커서 오른쪽, 행의 끝에 문자 삽입
i 커서 왼쪽에 문자 삽입
I 커서 왼쪽, 행의 처음에 문자 삽입
o 커서 아래에 행 삽입
O 커서 위에 행 삽입
ESC 종료

텍스트 변경 명령어

명령어 설명
cw 단어 변경
cc 행 변경
C 커서 오른쪽의 행 변경
s 커서가 위치한 문자열 대체
S 커서가 위치한 라인의 문자열 대체
r 커서 위치 문자를 다른 문자로 대체
r-Enter 행 분리
J 현재 행과 아래 행 결합
xp 커서 위치 문자와 오른쪽 문자 교환
~ 문자형(대, 소문자) 변경
u 이전 명령 취소
U 행 변경 사항 취소, 이전의 최종 행 취소
. 이전 최종 명령 반복

텍스트 삭제 명령어

명령어 설명
x 커서가 있는 문자 삭제
nx 커서가 있는 위치부터 n개의 문자를 삭제
dw 현재 커서에 있는 한 단어 삭제
dd 커서가 있는 라인 삭제
ndd 커서가 있는 라인부터 n개의 라인 삭제
db 커서의 위치에서 거꾸로 한 단어 삭제
D 커서 오른쪽 행 삭제
:5,10d 5~10번째 행 삭제

복사 및 이동 명령어

명령어 설명
yy 커서가 위치한 줄 복사
Y 행 yank 또는 복사
yh 커서의 왼쪽 문자 복사
yl 커서에 위치한 문자 복사
yi 커서가 위치한 줄과 그 아랫줄 복사
yk 커서가 위치한 줄과 그 윗줄 복사
p yank 되거나 삭제된 행 현재 행 위로 삽입
P yank 되거나 삭제된 행 현재 행 아래에 삽입
:1,2 co 3 1~2행을 3행 다음으로 복사
:4,5 m 6 4~5행을 6행 위로 이동
  • yank : 홱 잡아당기다

한줄복사

해당 라인에서 ‘yy’, 즉 y를 두번 누르면 캐시에 저장이 된다.
붙여넣기를 원하는 곳으로 이동하여 ‘p’를 누르면 커서 다음 라인에 붙여넣기가 된다.

블럭복사

‘v’키를 누른 후 커서를 이동하여 블력을 설정한다.
(putty의 경우 블럭이 설정되는 모습이 보이나, ssh의 경우 블럭 모습이 나타나지 않으나 실제로는 설정되고 있다.)
원하는 부분을 블럭으로 설정한 뒤(설정 완료키는 없다) ‘y’키를 누르면 캐시에 복사가 된다.
같은 방법으로 원하는 곳으로 이동하여 ‘p’를 누르면 커서 다음 라인에 붙여넣기가 된다.

행 번호 설정 명령어

명령어 설명
:set nu 또는 :set number 에디터의 각 행의 좌측에 행 번호 표시.
:set nonu 에디터의 각 행의 좌측 행 번호 숨기기

행 찾기 명령어

명령어 설명
G 파일의 마지막 행으로 가기
21G 파일의 21번째 행으로 가기
Ctrl + G 현재 File name과 커서의 라인 정보

탐색 및 대체 명령어

명령어 설명
/{검색할 문자열} 오른쪽 아래 방향으로 문자열 검색
?{검색할 문자열} 왼쪽 위 방향으로 문자열 검색
n 문자열의 다음으로 계속 검색
N 문자열의 이전으로 계속 검색
:g/search-string/s/ 각 발생 탐색 후 확인하고 대체
:s/string/rep 현재 행의 str을 rep로 대체
:1,.s/string/rep/ 1부터 현재 행의 str을 rep로 대체
:%s/string/rep/g 파일 전체 str을 rep로 전부대체
:.$/aaa/bbb 커서의 위치로부터 파일의 끝까지 있는 모든 aaa를 bbb로 대체

화면 정리 명령어

명령어 설명
Ctrl + l 불필요한 화면정리 후 다시 표시

파일 명령어

명령어 설명 예제
:r {파일명} 커서 다음에 파일 삽입 :r test.txt
:{행번호} r {파일명} 입력한 파일을 입력한 행번호 다음에 삽입 :10 r test.txt

보관 및 종료 명령어

명령어 설명
:w 변경사항 저장
:w {파일명} 변경사항 입력한 파일명으로 저장
:wq 변경사항 보관 후 vi 종료. ZZ 명령과 같음. :w(기록)과 :q(종료) 를 연속적으로 수행.
ZZ 변경사항 보관 후 vi 종료. 임시 버퍼의 내용을 vi로 호출할때 사용되었던 파일에 기록한 후 vi를 빠져나옴.
:q! 변경사항 보관하지 않고 종료
q 수정한 파일을 저장하지 않고 vi 종료
e! 수정한 것을 무시하고 다시 편집상태로

기타

문자 설명
. 현재 line
% 전체 line
$ 파일 맨끝 line
1,$ %
2,3 2 ~ 3 line

참고

http://blog.naver.com/youngrimi/50086851943

2.6.2 - Linux 명령어 | 쉘 스크립트 (Shell Script) | if 문, for 문, while 문 사용법 및 조건식

if 문 사용법, 조건식

기본 형식

if [값 조건식 값 조건식...]
then
    수행문
elif [값 조건식 값 조건식...]
then
    수행문
else
    수행문
fi

조건식 종류

조건식 설명
-z 문자열의 길이가 0이면 참
-n 문자열의 길이가 0이 아니면 참
-eq 값이 같으면 참. = 연산자 동일
-ne 값이 다르면 참
-gt 값1 > 값2
-ge 값1 >= 값2
-lt 값1 < 값2
-le 값1 <= 값2
-a &&연산과 동일 and 연산
-o ||연 산과 동일 xor 연산
-d 파일이 디렉토리면 참
-e 파일이 있으면 참
-L 파일이 심볼릭 링크면 참
-r 파일이 읽기 가능하면 참
-s 파일의 크기가 0 보다 크면 참
-w 파일이 쓰기 가능하면 참
-x 파일이 실행 가능하면 참
파일1 -nt 파일2 파일1이 파일2보다 최신파일이면 참
파일1 -ot 파일2 파일1이 파일2보다 이전파일이면 참
파일1 -ef 파일2 파일1이 파일2랑 같은 파일이면 참

예시

#!/bin/bash

value=0 #value = 0 이렇게 변수와 값 사이에 공백을 입력하면 syntax 에러가 발생한다.

if [ $value = 0 ]
then
	echo "value is 0"
else
	echo "value is not 0"
fi

실행 결과

$ ./test.sh
value is 0

for 문 사용법

기본 형식

for [변수] in [반복 조건]
do
    [실행문]
done

예시)

#!/bin/bash

for i in 1 2 3
do
    echo "$i"
done

실행 결과

$ ./test.sh
1
2
3

while 문 사용법, 조건식

기본 형식

while [ 값1 조건식 값2 ]
do
   [실행문]
   [실행문]
done 

예시)

i=0

while [ $i -lt 3 ]
do
    echo $i
     i=$(($i+1))
done

실행 결과

$ ./test.sh 
0
1
2

2.6.3 - Linux 명령어 | 쉘 스크립트 (Shell Script) | Shell 인자, 파라미터 사용법

Shell 스크립트에서 파라미터 입력 방법에 대해 알아보자.

파라미터 관련 문자

  • $# : 파라미터 개수를 반환하다.
  • $숫자: 숫자를 입력하여 입력받은 순번의 파라미터를 반환한다.
  • $@: 모든 파라미터를 반환하다.

예제

먼저 파일을 만들고

$ vi cmd.sh

아래와 같이 내용을 작성한다.

#!/bin/bash

echo "파라미터 개수 : $#"
echo "첫 번째 파라미터: $1"
echo "두 번째 파라미터: $2"
echo "모든 파라미터 내용 : $@"

내용이 작성이 되면 파일에 실행 권한을 지정한다.

$ chmod 755 cmd.sh 

실행 결과:

$ ./cmd.sh hello devkuma
파라미터 개수 : 2
첫 번째 파라미터: hello
두 번째 파라미터: devkuma
모든 파라미터 내용 : hello devkuma

응용

톰켓 재시작 셀 스크립트

kill -9 $(ps aux |awk '/tomcat/ {print $2}')
sleep 2
/home/ubuntu/tomcat/bin/startup.sh

2.7 - Linux 명령어 | 그밖에

그밖에 리눅스 명령어에 대해서 설명한다.

2.7.1 - Linux 명령어 | 그밖에 | logout 사용자 로그아웃

logout 명령어

사용자 로그아웃을 한다.

사용법

logout

2.7.2 - Linux 명령어 | 그밖에 | shutdown 시스템 종료

shutdown 명령어

시스템을 종료할 때 일반적으로 사용된다.

사용법

shutdown [옵션] 시간 [메세지]

option

-t n t 옵션 뒤에 n초를 명시해서, 경고 메시지를 보낸후 n초 후에 kill 시그널을 보냄 -h : shutdown시 halt를 실행 -r : 시스템 종료를 완료하고 나서 다시 부팅 과정을 수행(리부팅) -c : 이미 예약되어 있는 shutdown을 취소 -k : 모든 동작을 제대로 수행하지만 시스템을 종료할 시간이 되면 아무것도 하지 않음. ksms ‘just kidding’의 의미

2.7.3 - Linux 명령어 | 그밖에 | alias 명령어 치환

alias 명령어

복잡한 명령어와 옵션을 간단히 입력할 수 있는 문자열로 치환한다.

사용법

alias [단축키]='[명령어]'

alias 명령어 사용 예제

예제 1)

alias로 지정된 명령어 확인한다.

alias

예제 2)

clear 명령어 대신 c를 입력해도 같은 기능을 하게 만든다.

alias c='clear'

예제 3)

mkdir -p a/b/c 명령어 대신 m을 입력해도 같은 기능을 하게 만든다.

alias m='mkdir -p a/b/c'

alias 명령어 영구 저장

설정 해 놓은 alias는 창이 꺼지면 다 사라진다.
영구적으로 저장 하고 싶을땐 .bashrc에 저장 하면 된다.
.bashrc의 위치는 ~계정명/.bashrc 이다.
A라는 계정에서 저장한 alias명령어는 B라는 계정에서 사용 불가능하다.

저장법 :

  1. cat » ~root/.bashrc 입력
  2. 자신이 저장 할 alias 입력
  3. 엔터 친뒤 Ctrl + C
  4. 창을 껐다가 키거나, 아래 명령어을 입력한다.
  • chsh -s /bin/bash

2.7.4 - Linux 명령어 | 그밖에 | clear 화면 정리

clear 명령어

리눅스 최초 실행 시의 화면처럼 정리한다.

clear

2.7.5 - Linux 명령어 | 그밖에 | history 사용한 명령어 이력

history 명령어

리눅스 접속 후 사용한 명령어 이력 관리를 해준다.

사용법

$ history

이전 이력 삭제

$ history -c

이력은 메모리에 저장이 되는데, .bash 셀이 종료할 경우 즉, 시스템 종료 및 로그아웃을 할 경우 이력이 홈 디렉토리에 있는 .bash_history 파일에 자동으로 저장된다. 이는 수동으로 현재 이력을 저장할 수 있는데 이때는 -w 옵션을 사용하면 된다.

현재 이력을 ~/.bash_history 파일에 저장

$ history -w

과거 이력을 모두 지우고 싶은 경우에는 -c , -w 옵션을 모두 사용하여 메모리 및 .bash_history 파일을 갱신하면 된다.

$ history -c
$ history -w

2.7.6 - Linux 명령어 | 그밖에 | tree 디렉토리 구조 조회

tree란?

터미널에서 디렉토리 구조 조회를 용이하게 해준다.

ls 명령어를 사용해서 디렉토리 내부를 확인할 수 있기는 하지만, 서브 디렉토리 내부에 포함된 파일을 확인하려면 다시 cd, ls 명령어를 중복 사용해야 하는 불편함이 있다. 이럴 때 tree 명령어를 활용하면 한 눈에 디렉토리 구조를 파악할 수 있어 매우 유용하다.

tree 설치

기본적으로 tree 명령은 설치되지 않습니다.

RHEL / CentOS / Fedora Linux 환경에서 yum 으로 설치

$ yum install tree

Debian / Mint / Ubuntu Linux 환경에서 apt-get 으로 설치

$ sudo apt-get install tree

Mac OS 환경 에서 homebrew로 설치

$ brew install tree
Updating Homebrew...
==> Downloading https://homebrew.bintray.com/bottles/tree-1.7.0.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring tree-1.7.0.yosemite.bottle.1.tar.gz
/usr/local/Cellar/tree/1.7.0: 7 files, 113.4KB

tree 사용법

사용법

$ tree (옵션)

디렉토리 구조 조회

$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   └── java
    │       └── Library.java
    └── test
        └── java
            └── LibraryTest.java

7 directories, 8 files

tree 옵션

옵션 설명
-a 숨겨진 파일 포함 모두 표시
-d 디렉토리 구조만 표시
-l 디렉토리와 같은 기호 링크를 따라 가서 표시.
-f 상대 경로로 표시
-i 들여쓰기를 적용하지 않고 표시
-q 출력할 수 없는 ‘?’ 문자까지 표시.
-N 출력할 수 없는 문자까지 모두 표시.
-p 퍼미션(권한) 설정까지 표시.
-u 파일 권한자 또는 UID 숫자 표시.
-g 각 파일의 용량(Bytes) 표시.
-h 각 파일의 용량 크기를 사람이 보기 편하게 표시.
-D 수정한 날짜 표시.
-F 뒤에 ‘/’, ‘=’, ‘*’, 또는 ‘|’ 붙여 사용.
-v 디렉토리 내 파일을 알파벳 순으로 정렬.
-r 디렉토리 내 파일을 알파벳 역순으로 정렬.
-t 최근 수정한 파일 순으로 정렬.
-x 현재 파일 시스템만 나둠.
-n 컬러 모드 표시 Off.
-C 컬러 모드 표시 On.

참조

2.7.7 - Linux 명령어 | 그밖에 | apt-get 패키지 관리

apt-get 명령어

APT는 Advanced Package Tool의 약자이다.
ftp 또는 http 프로토콜을 사용하여 인터넷을 통한 패키지 설치를 지원한다.
단일 작업으로 모든 패키지를 업그레이드 할 수 있으므로 훨씬 더 매력적이다.
스크립팅 목적으로 apt-get는 완벽한 도구이다

사용법

apt-get install {package-name}

사용 예

samba라는 패키지를 설치하려면 다음을 실행하십시오.

# apt-get install samba

OR

$ sudo apt-get install samba

참고

https://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html

2.7.8 - Linux 명령어 | 그밖에 | yum 패키지 관리

yum이란?

  • 패키지 관리 시스템 중 하나이다.
  • Yellowdog Updater Modified의 약자. Yellowdog Updater의 개량판이다.
  • 듀크 대학의 Linux@DUKE 프로젝트에서 개발되었다.
  • Red Hat Enterprise Linux(RHEL), CentOS, Fedora 등 Red Hat 기반 Linux의 표준 패키지 관리 시스템으로 채택되었다.
  • RPM에서는 패키지의 URL을 버전 번호까지 포함하여 지정하고 하나씩 설치하였지만, yum은 패키지 설치에 대한 최신 버전을 설치, 종속성이 있는 패키지를 자동으로 설치, 키워드로 패키지 를 검색하는 등의 기능이 있다.
  • RHEL 8 / CentOS 8부터 yum 명령은 dnf 명령으로 변경되었지만 인수는 거의 변경되지 않았으며 dnf 명령에서도 다음 명령을 사용할 수 있다.

Yum 사용 방법

패키지 설치

# yum install <패키지명>
# yum -y install <패키지명>	 # 설치? (y/N) 입력 생략

업데이트 버전이 있는 패키지 확인

# yum check-update

특정 패키지 업데이트

# yum update <패키지명>

모든 패키지 업데이트

# yum update
# yum upgrade ← yum update --obsoletes와 동일

패키지 삭제

# yum erase <패키지명>

설치된 패키지 목록 보기

# yum list installed

설치 가능한 패키지 목록 보기

# yum list

특정 단어가 포함된 패키지 찾기

# yum search <문자열>

패키지에 대한 자세한 정보 표시

# yum info <패키지명>

참조할 리포지토리 목록 보기

# yum repolist

리포지토리

yum은 패키지를 리포지토리에서 가져온다.

  • RHEL(Red Hat Enterprise Linux)의 경우 Red Hat 리포지토리 가져온다.
  • CentOS의 경우 CentOS 프로젝트에서 제공하는 리포지토리에서 패키지를 다운로드한다.

리포지토리 목록은 /etc/yum.repos.d 디렉토리 아래로 설정된다.

EPEL

Red Hat 및 CentOS Project에서 제공하는 표준 리포지토리 외에도 Fedora 프로젝트에서 제공하는 EPEL(Extra Packages for Enterprise Linux) 리포지토리가 있다. 표준 저장소만큼 안정적이지는 않지만 확장 패키지가 포함되어 있다.

EPEL을 참조하려면 EPEL 저장소 구성 파일을 /etc/repos.d/ 아래에 설치하십시오.

# yum -y install epel-release

평소에는 EPEL 리포지토리를 무효로 해 두고, 커멘드 라인으로 지정했을 경우만 유효하게 하려면 , 다음과 같이 한다.

# vi /etc/yum.repos.d/epel.repo

enabled= 0

# yum install 패키지 이름 --enablerepo=epel

2.7.9 - Linux 명령어 | 그밖에 | Samba 설치 및 사용

리눅스에서 사용할 수 있는 Samba는 특정 디렉토리를 지정하여 다른 OS와 공유할 수 있게끔 해주는 프로그램이다.

윈도우의 경우 간편하게 작업그룹(WORK GROUP)간의 디렉토리 공유등을 할 수 있는 반면에 리눅스의 경우 NFS나 Samba를 이용하여 디렉토리를 타 OS와 공유하여 사용할 수 있다.

운영중인 서버중에 백업서버처럼 사용하는 서버가 있는데, 기존에는 필요할때만 FTP로 접속하여 파일을 보관하였다.

하지만 서비스중인 프로그램, 로그 등의 2차 백업을 위하여 해당 백업서버에 추가 백업을 진행하기로 결정하였고 이에 백업 서버에 Samba를 설치하여 각 서비스 서버에서 공유된 디렉토리를 Mount 하여 자동으로 백업되게끔 구성하였다.

오늘은 리눅스에 Samba를 설치하고 다른 OS에서 Mount 하여 사용하는 방법에 대해 알아보자.

Samba 서버 설치하기

Samba 패키지 설치

$yum install -y samba 

환경설정

$ vi /etc/samba/smb.conf

# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options (perhaps too
# many!) most of which are not shown in this example
#
# For a step to step guide on installing, configuring and using samba, 
# read the Samba-HOWTO-Collection. This may be obtained from:
#  http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf
#
# Many working examples of smb.conf files can be found in the 
# Samba-Guide which is generated daily and can be downloaded from: 
#  http://www.samba.org/samba/docs/Samba-Guide.pdf
#
# Any line which starts with a ; (semi-colon) or a # (hash) 
# is a comment and is ignored. In this example we will use a #
# for commentry and a ; for parts of the config file that you
# may wish to enable
#
# NOTE: Whenever you modify this file you should run the command "testparm"
# to check that you have not made any basic syntactic errors. 
#
#---------------
# SELINUX NOTES:
#
# If you want to use the useradd/groupadd family of binaries please run:
# setsebool -P samba_domain_controller on
#
# If you want to share home directories via samba please run:
# setsebool -P samba_enable_home_dirs on
#
# If you create a new directory you want to share you should mark it as
# "samba_share_t" so that selinux will let you write into it.
# Make sure not to do that on system directories as they may already have
# been marked with othe SELinux labels.
#
# Use ls -ldZ /path to see which context a directory has
#
# Set labels only on directories you created!
# To set a label use the following: chcon -t samba_share_t /path
#
# If you need to share a system created directory you can use one of the
# following (read-only/read-write):
# setsebool -P samba_export_all_ro on
# or
# setsebool -P samba_export_all_rw on
#
# If you want to run scripts (preexec/root prexec/print command/...) please
# put them into the /var/lib/samba/scripts directory so that smbd will be
# allowed to run them.
# Make sure you COPY them and not MOVE them so that the right SELinux context
# is applied, to check all is ok use restorecon -R -v /var/lib/samba/scripts
#
#--------------
#
#======================= Global Settings =====================================
    
[global]
    
# ----------------------- Network Related Options -------------------------
#
# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
#
# server string is the equivalent of the NT Description field
#
# netbios name can be used to specify a server name not tied to the hostname
#
# Interfaces lets you configure Samba to use multiple interfaces
# If you have multiple network interfaces then you can list the ones
# you want to listen on (never omit localhost)
#
# Hosts Allow/Hosts Deny lets you restrict who can connect, and you can
# specifiy it as a per share option as well
#
    workgroup = MYGROUP    // 윈도우에서 공유될 workgroup 명
    server string = Samba Server Version %v        // 공유될 서버 이름
    
;    netbios name = MYSERVER
    
;    interfaces = lo eth0 192.168.12.2/24 192.168.13.2/24 
    hosts allow = 127. 192.168.12. 192.168.13.
    // 허용 ip 또는 ip 대역을 지정
    
# --------------------------- Logging Options -----------------------------
#
# Log File let you specify where to put logs and how to split them up.
#
# Max Log Size let you specify the max size log files should reach
    
    # logs split per machine
    log file = /var/log/samba/log.%m
    # max 50KB per log file, then rotate
    max log size = 50
    
# ----------------------- Standalone Server Options ------------------------
#
# Scurity can be set to user, share(deprecated) or server(deprecated)
#
# Backend to store user information in. New installations should 
# use either tdbsam or ldapsam. smbpasswd is available for backwards 
# compatibility. tdbsam requires no further configuration.

    security = user        //리눅스 계정 ID로 접속 가능(share : 사용자 인증없이 모두 접속 가능)
    passdb backend = tdbsam


# ----------------------- Domain Members Options ------------------------
#
# Security must be set to domain or ads
#
# Use the realm option only with security = ads
# Specifies the Active Directory realm the host is part of
#
# Backend to store user information in. New installations should 
# use either tdbsam or ldapsam. smbpasswd is available for backwards 
# compatibility. tdbsam requires no further configuration.
#
# Use password server option only with security = server or if you can't
# use the DNS to locate Domain Controllers
# The argument list may include:
#   password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
# or to auto-locate the domain controller/s
#   password server = *
    
    
;    security = domain
;    passdb backend = tdbsam
;    realm = MY_REALM

;    password server = <NT-Server-Name>

# ----------------------- Domain Controller Options ------------------------
#
# Security must be set to user for domain controllers
#
# Backend to store user information in. New installations should 
# use either tdbsam or ldapsam. smbpasswd is available for backwards 
# compatibility. tdbsam requires no further configuration.
#
# Domain Master specifies Samba to be the Domain Master Browser. This
# allows Samba to collate browse lists between subnets. Don't use this
# if you already have a Windows NT domain controller doing this job
#
# Domain Logons let Samba be a domain logon server for Windows workstations. 
#
# Logon Scrpit let yuou specify a script to be run at login time on the client
# You need to provide it in a share called NETLOGON
#
# Logon Path let you specify where user profiles are stored (UNC path)
#
# Various scripts can be used on a domain controller or stand-alone
# machine to add or delete corresponding unix accounts
#
;    security = user
;    passdb backend = tdbsam
    
;    domain master = yes 
;    domain logons = yes
    
    # the login script name depends on the machine name
;    logon script = %m.bat
    # the login script name depends on the unix user used
;    logon script = %u.bat
;    logon path = \\%L\Profiles\%u
    # disables profiles support by specifing an empty path
;    logon path =          
    
;    add user script = /usr/sbin/useradd "%u" -n -g users
;    add group script = /usr/sbin/groupadd "%g"
;    add machine script = /usr/sbin/useradd -n -c "Workstation (%u)" -M -d /nohome -s /bin/false "%u"
;    delete user script = /usr/sbin/userdel "%u"
;    delete user from group script = /usr/sbin/userdel "%u" "%g"
;    delete group script = /usr/sbin/groupdel "%g"
    
    
# ----------------------- Browser Control Options ----------------------------
#
# set local master to no if you don't want Samba to become a master
# browser on your network. Otherwise the normal election rules apply
#
# OS Level determines the precedence of this server in master browser
# elections. The default value should be reasonable
#
# Preferred Master causes Samba to force a local browser election on startup
# and gives it a slightly higher chance of winning the election
;    local master = no
;    os level = 33
;    preferred master = yes
    
#----------------------------- Name Resolution -------------------------------
# Windows Internet Name Serving Support Section:
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
#
# - WINS Support: Tells the NMBD component of Samba to enable it's WINS Server
#
# - WINS Server: Tells the NMBD components of Samba to be a WINS Client
#
# - WINS Proxy: Tells Samba to answer name resolution queries on
#   behalf of a non WINS capable client, for this to work there must be
#   at least one    WINS Server on the network. The default is NO.
#
# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
# via DNS nslookups.
    
;    wins support = yes
;    wins server = w.x.y.z
;    wins proxy = yes
    
;    dns proxy = yes
    
# --------------------------- Printing Options -----------------------------
#
# Load Printers let you load automatically the list of printers rather
# than setting them up individually
#
# Cups Options let you pass the cups libs custom options, setting it to raw
# for example will let you use drivers on your Windows clients
#
# Printcap Name let you specify an alternative printcap file
#
# You can choose a non default printing system using the Printing option
    
    load printers = yes
    cups options = raw

;    printcap name = /etc/printcap
    #obtain list of printers automatically on SystemV
;    printcap name = lpstat
;    printing = cups

# --------------------------- Filesystem Options ---------------------------
#
# The following options can be uncommented if the filesystem supports
# Extended Attributes and they are enabled (usually by the mount option
# user_xattr). Thess options will let the admin store the DOS attributes
# in an EA and make samba not mess with the permission bits.
#
# Note: these options can also be set just per share, setting them in global
# makes them the default for all shares

;    map archive = no
;    map hidden = no
;    map read only = no
;    map system = no
;    store dos attributes = yes


#============================ Share Definitions ==============================

[sambaDir]
    comment = Test
    path = /data/sambaDir    // 공유 디렉토리
    browseable = no
    writable = yes        // 읽고 쓰기 허용 옵션
    valid users = tour    // 특정 계정에 대해서만 공유 허용


[homes]
    comment = Home Directories
    browseable = no
    writable = yes
;    valid users = %S
;    valid users = MYDOMAIN\%S
    
[printers]
    comment = All Printers
    path = /var/spool/samba
    browseable = no
    guest ok = no
    writable = no
    printable = yes
    
# Un-comment the following and create the netlogon directory for Domain Logons
;    [netlogon]
;    comment = Network Logon Service
;    path = /var/lib/samba/netlogon
;    guest ok = yes
;    writable = no
;    share modes = no
    
    
# Un-comment the following to provide a specific roving profile share
# the default is to use the user's home directory
;    [Profiles]
;    path = /var/lib/samba/profiles
;    browseable = no
;    guest ok = yes
    
    
# A publicly accessible directory, but read only, except for people in
# the "staff" group
;    [public]
;    comment = Public Stuff
;    path = /home/samba
;    public = yes
;    writable = yes
;    printable = no
;    write list = +staff

Samba 서비스 시작/종료/재시작

Samba 시작

$ service smb start
SMB서비스를 시작하고 있습니다:                             [  OK  ]

Samba 종료

$ service smb stop
SMB 서비스를 종료함:                                       [  OK  ]

Samba 재시작

$ service smb restart
SMB서비스를 시작하고 있습니다:                             [  OK  ]
SMB 서비스를 종료함:                                       [  OK  ]

로그인 계정의 패스워드 지정

접속방식을 sercurity = user로 지정했을경우에, 리눅스 계정과는 별도로 Samba 패스워드를 등록해야 한다.

tour 계정의 패스워드 지정

$ smbpasswd -a tour

tour 계정의 samba 계정 삭제

$ smbpasswd -x tour

tour 계정의 samba 사용을 중지

$ smbpasswd -d tour

iptables 방화벽 규칙 추가(iptables 이용시)

iptables 설정파일 열기

$ vi /etc/sysconfig/iptables

해당내용 추가 후 저장

-A INPUT -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 445 -j ACCEPT

iptables 재시작

$ service iptables restart
iptables: 체인을 ACCEPT 규칙으로 설정 중:  filter          [  OK  ]
iptables: 방화벽 규칙을 지웁니다:                          [  OK  ]
iptables: 모듈을 언로드하는 중:                            [  OK  ]
iptables: 방화벽 규칙 적용 중:                             [  OK  ]

Samba 디렉토리 마운트하기

디렉토리 생성

$ cd /mnt
$ mkdir sambaDir

디렉토리 마운트하기

// Samba 서버의 ip(192.168.0.23)과 공유 디렉토리, 그리고 마운트될 디렉토리를 지정
$ mount -t cifs -o username=tour //192.168.0.23/sambaDir /mnt/sambaDir

부팅시 Samba디렉토리 마운트 하기

$ vi /etc/fstab 

// 아래내용 추가
//192.168.0.23/sambaDir   /mnt/sambaDir      cifs    username='tour',password='abcd!@'   0 0

**TIP) ** 일반 사용자 계정으로 마운트시에는 다음과 같이 사용자의 uid, gid를 추가하면 된다

tour 계정 uid 확인 (tour 계정 로그인 상태에서…)

$ id
uid=500(tour) gid=500(tour) groups=500(tour)

tour 계정으로 마운트(root 계정 로그인 상태에서)

$ mount -t cifs -o username=tour,uid=500,gid=500 //192.168.0.23/sambaDir /mnt/sambaDir 

fstab에도 uid,gid 추가

//192.168.0.23/sambaDir   /mnt/sambaDir     cifs    username='tour',password='abcd!@',uid=500,gid=500   0 0 
  • 마운트 확인후 공유된 디렉토리에 파일 생성 또는 디렉토리 만들기 등을 통해 정상적으로 생성이 되는지 확인한다.
    만약 “허가 권한” 등과 같이 오류가 나올때는 Samba 서버의 Selinux가 켜져 있는지 확인한 후 Selinux를 끈 후 테스트해 본다.

Selinux 끄기 (Samba 서버에서)

$ setenforce 0

출처

2.7.10 - Linux 명령어 | 그밖에 | su 계정 변경

su 명령어

다른 사용자 계정으로 서브 쉘을 생성하는 것으로, 잠시동안 다른 사용자 계정으로 작업할 필요가 있을 때 사용한다.
많은 사람들이 su가 ‘super user’를 의미하는 말로 생각하지만, 사실은 ‘substitute user’를 의미한다.

사용법

su [-] [사용자ID][인수]

option

  • 하이픈(-)을 사용하면 새로운 쉘로 로그인할 때 자신의 로그인 과정을 수행한다. 옵션이 주어지지 않으면 새로운 쉘은 단지 쉘 역할을 수행할 뿐이다.

2.7.11 - Linux 명령어 | 그밖에 | finger 사용자 정보 조회

finger 명령어

시스템 상의 사용자의 대한 정보를 조회한다.
인수로 아무 것도 주어지지 않으면, finger는 현재 시스템에 로그인되어 있는 사용자들을 보여준다.

사용법

finger [-slpm] [사용자]

option

  • -s :사용자의 로그온 이름, 실제 이름, 터미널 이름, 로그온 시간 등을 표시한다.
  • -l -s : 옵션 정보에 몇 가지를 추가하여, 여러 줄에 걸쳐서 표시한다.
  • -p -l : 옵션 정보에서 .plan과 .project 파일을 보이지 않는다.

예제

$ finger kimkc
Login: kimkc          			Name: kimkc
Directory: /Users/kimkc             	Shell: /bin/bash
On since 토  3 16 10:07 (KST) on console, idle 16:02 (messages off)
On since 토  3 16 23:36 (KST) on ttys000
No Mail.
No Plan.

2.7.12 - Linux 명령어 | 그밖에 | cal 달력 조회

cal 명령어

cal은 calendar의 약자이다.
서기 원년부터 9999년까지의 달력을 볼 수 있다.
인수를 하나만 준다면 그 숫자는 연도를 의미하는 것으로 간주된다.
두 개의 숫자를 준다면 앞의 것을 월, 그 다음은 연도를 의미한다.

사용법

cal [-jy] [ [달] 연도]

option

  • -j : 1월 1일 부터 날짜 수를 계산하는 julian 날짜를 표시한다.
  • -y : 올해의 달력을 표시한다.

cal 명령어 사용 예제

예제1)

$ cal
      3월 2019         
일 월 화 수 목 금 토  
                1  2  
 3  4  5  6  7  8  9  
10 11 12 13 14 15 16  
17 18 19 20 21 22 23  
24 25 26 27 28 29 30  
31     

예제2)

$ cal -j
          3월 2019            
 일  월  화  수  목  금  토  
                     60  61  
 62  63  64  65  66  67  68  
 69  70  71  72  73  74  75  
 76  77  78  79  80  81  82  
 83  84  85  86  87  88  89  
 90     

2.7.13 - Linux 명령어 | 그밖에 | date 시간 표시 및 변경

date 명령어

date는 위아 같이 주어진 인수가 없다면 현재 시스템의 시간과 날짜를 출력한다.
만약 주어지는 옵션이 있다면 그에 따라서 시스템의 시간과 날짜를 변경한다.

문법

date [yymmddhhmm [ss] ]

매개 변수 설명

  • yy는 연도를 나타내는 두 숫자이며, mm은 월을 나타낸다. dd는 날짜를 나타낸다.
  • hh는 24시간 단위로 표현 되며, mm은 분을 의미한다.
  • 마지막에 있는 ss는 초를 의미하는 부분으로 명시하지 않아도 상관없다.

date 명령어 사용 예제

예시

$ date
2019년 3월 17일 일요일 02시 23분 03초 KST

2.7.14 - Linux 명령어 | 그밖에 | FTP

FTP로 들어온 사용자 확인하기

  • ftpwho
  • ftpcount

특정 사용자 ftp 접근 막기

/etc/ftpusers 파일에 로그인 네임을 추가하면 된다.

2.7.15 - Linux 명령어 | 그밖에 | 컴퓨터(호스트) 이름 변경하기

CentOS 7 이상부터는 명령어로 변경하는 방법

아래와 같이 명령어로 새로운 호스트명을 입력하여 실행한다.

$ hostnamectl set-hostname [새로운 호스트명]

명령어가 실행한 후에는 콘솔을 닫았다가 다시 켜면 된다.

hostname 확인 명령어

$ hostname

3 - Mac OS

Mac OS

Mac OS

3.1 - Mac OS | Homebrew 패키지 관리자

Homebrew이란?

Homebrew를 설치하면 패키지 버전 관리가 용이하다.

Ubuntu나 SentOS에서 제공해주는 패키지 관리자로는 apt-get이나 yum가 있다. Mac에서는 이런 패키지 관리자도 제공해주지 않기 때문에 직접 설치를 해야 한다.

Homebrew 설치

터미널 창에서 아래 명령어를 입력 후에 실행한다.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

설치 성공

==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew

Press RETURN to continue or any other key to abort
==> Downloading and installing Homebrew...
remote: Counting objects: 95726, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 95726 (delta 3), reused 8 (delta 3), pack-reused 95717
Receiving objects: 100% (95726/95726), 21.86 MiB | 127.00 KiB/s, done.
Resolving deltas: 100% (69501/69501), done.
From https://github.com/Homebrew/brew
 * [new branch]          master     -> origin/master
 * [new tag]             0.1        -> 0.1
 * [new tag]             0.2        -> 0.2

... 중략 ...

 * [new tag]             1.4.0      -> 1.4.0
HEAD is now at b4d43e950 Merge pull request #3401 from DomT4/vendor_or_na
==> Tapping homebrew/core
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core'...
remote: Counting objects: 4673, done.
remote: Compressing objects: 100% (4415/4415), done.
remote: Total 4673 (delta 62), reused 1098 (delta 46), pack-reused 0
Receiving objects: 100% (4673/4673), 3.81 MiB | 116.00 KiB/s, done.
Resolving deltas: 100% (62/62), done.
Tapped 4445 formulae (4,720 files, 12.0MB)
==> Cleaning up /Library/Caches/Homebrew...
==> Migrating /Library/Caches/Homebrew to /Users/sanghopark/Library/Caches/Homebrew...
==> Deleting /Library/Caches/Homebrew...
Already up-to-date.
==> Installation successful!

==> Homebrew has enabled anonymous aggregate user behaviour analytics.
Read the analytics documentation (and how to opt-out) here:
  https://docs.brew.sh/Analytics.html

==> Next steps:
- Run `brew help` to get started
- Further documentation: 
    https://docs.brew.sh

설치 실패

혹시 설치 시에 아래와 같이 에러가 발생하여 설치가 되지 않을 수가 있다.

Press RETURN to continue or any other key to abort
You have not agreed to the Xcode license.
Before running the installer again please agree to the license by opening
Xcode.app or running:
    sudo xcodebuild -license

이럴 때는 Xcode를 설치하고 동의를 누르지 않아서 발생한 것이다. 이럴때는 xcode를 최초 실행하고 Agree를 눌려주면 된다.

Homebrew 사용법

버전 확인

$ brew -v
Homebrew 1.3.1
Homebrew/homebrew-core (git revision d6b4; last commit 2017-08-16)

패키지 설치

$ brew install {프로그램명}

패키지 비활성화 및 활성화

$ brew unlink {프로그램명} # 일시적으로 비활성화
$ brew link {프로그램명}   # 활성화

패키지 목록 업데이트

$ brew update   # formula를 업데이트
$ brew upgrade  # 업데이트 패키지를 다시 빌드

설치된 목록보기

$ brew list

패키지 제거

$ brew remove {프로그램명}

Homebrew 설정 목록

$ brew --config
HOMEBREW_VERSION: 1.3.1
ORIGIN: https://github.com/Homebrew/brew
HEAD: 69799d97b1e7314912b2ee234dec2c179c5fb969
Last commit: 9 days ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: d6b4b6ba05bbff6a3731f80580ebee7574bf6494
Core tap last commit: 2 hours ago
HOMEBREW_PREFIX: /usr/local
HOMEBREW_REPOSITORY: /usr/local/Homebrew
HOMEBREW_CELLAR: /usr/local/Cellar
HOMEBREW_BOTTLE_DOMAIN: https://homebrew.bintray.com
CPU: quad-core 64-bit sandybridge
Homebrew Ruby: 2.0.0-p481
Clang: 7.0 build 700
Git: 2.4.9 => /Applications/Xcode.app/Contents/Developer/usr/bin/git
Perl: /usr/bin/perl
Python: /usr/bin/python
Ruby: /usr/bin/ruby => /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby
Java: 1.8.0_121
macOS: 10.10.5-x86_64
Xcode: 7.1.1
CLT: N/A
X11: N/A

Homebrew 제거

$ cd `brew --prefix`
$ rm -rf Cellar
$ brew prune
$ rm `git ls-files`
$ rmdir Library/Homebrew Library/Aliases Library/Formula Library/Contributions
$ rm -rf .git
$ rm -rf ~/Library/Caches/Homebrew

참고

https://brew.sh/index_ko.html
https://github.com/mimul/dev-environment/blob/master/mac-homebrew.md

3.2 - Mac OS | 키보드 기호

기호 키보드
command 키
control 키
option 키
shift 키
caps lock
Fn 기능 키

3.3 - Mac OS | 파일 자르기/붙이기 방법

파일 자르기/붙이기 방법

라이온 부터는 자르기/붙이기가 단축키로 지원이 된다.. 다만 윈도우즈와는 조금 다른데요, 윈도우즈는 잘라낸 후 붙이는 방식인데 라이온은 복사를 한 후 붙이거나 이동하는 방법입니다. 맥에서는 선택권이 두가지가 되는것이죠. 아래 명령어는 라이온에서만 가능하다.

먼저 command + c 로 복사를 한 후 command + v로 붙여넣거나 command + option + v 로 잘라내어 붙인다.

  1. 복사하기 / 붙이기 : command + c / command + v
  2. 복사하기 / 이동하기 : command + c / command + option + v

참조

http://www.appleblog.co.kr/맥에서도-파일-잘라내기-붙이기-cut-paste가-가능합니다/

3.4 - Mac OS | Finder 숨기 파일 설정

Finder 숨기 파일 보이게 하기

터미널에서 아래 명령어를 실행한다.

$ defaults write com.apple.Finder AppleShowAllFiles YES

Finder 숨긴 파일 안 보이게 하기

터미널에서 아래 명령어를 실행한다.

$ defaults write com.apple.Finder AppleShowAllFiles NO

파인더 재시작

$ killall -KILL Finder

NOTE : 설정을 변경하고 파인더를 재시작을 해줘야 함.

3.5 - Mac OS | 스크린샷 그림자 제외

개요

⌘ Command + ⇧Shift + 5를 누른 후에 Space를 누르면, 포인터가 카메라 모양으로 바뀌고 클릭을 하면 창 모양이 캡쳐가 된다. 이때, 창의 그림자가 포함된다. 깔끔해서 좋을 때도 있지만 그림자 영역이 불필요할 때도 있다.

그림자 제외 처리

[Finder]-[응용 프로그램]-[유틸리티]-[터미널]에서 다음 명령어를 실행한다.

$ defaults write com.apple.screencapture disable-shadow -bool true
$ killall SystemUIServer

원상 복구

$ defaults write com.apple.screencapture disable-shadow -bool false
$ killall SystemUIServer

참조

https://zetawiki.com/wiki/맥_스크린샷_그림자_제외

3.6 - Mac OS | 파일 복사하기, 붙이기, 이동하기

라이온 부터는 자르기/붙이기가 단축키로 지원이 된다. 다만 윈도우즈와는 조금 다르다. 윈도우즈는 잘라낸 후 붙이는 방식인데, 라이온은 복사를 한 후에 붙이거나 이동하는 방법이다. 맥에서는 선택권이 두가지가 되는 거다.

먼저 command + c 로 복사를 한 후 command + v로 붙여넣거나 command + option + v 로 잘라내어 붙인다.

복사하기 / 붙이기

command + c / command + v

복사하기 / 이동하기

command + c / command + option + v

3.7 - Mac OS | 한글 키보드 원화(₩) 대신에 백쿼트(`) 입력하기

macOS Sierra로 업데이트된 이후 키보드가 한글인 상태에서는 백 쿼트(`) 키를 누르면 원화(₩)가 입력된다.

한글 입력 상태에서는 옵션키와 함께 백 쿼트(`)키를 눌러야 백 쿼트(`)를 입력할 수 있다.

마크다운 문서를 작성하는 사람이나 개발자에게는 매우 불편하다.

해결 방법

~/Library 디렉토리 이동해서 KeyBindings 로 이동한다. 혹시 없다면 디렉토리를 만든다.

$ cd ~/Library
$ mkdir KeyBindings > 이미 디렉토리 생성 명령어(이미 디렉토리가 있다면 생략한다)

~/Library/KeyBindings 디렉토리에 DefaultkeyBinding.dict 파일을 생성한다.

$ touch DefaultkeyBinding.dict > 파일 생성 명령어(이미 파일이 있다면 생략한다.)

DefaultkeyBinding.dict 파일에 vi명령어  등의 편집기로 아래의 코드를 추가한다.

{
    "₩" = ("insertText:", "`");
}

그러고 애플리케이션을 종료 후에 새로 실행하면 한글 입력 상태에서도 백 쿼트(`)가 입력되는 것을 확인할 수 있다.

3.8 - Mac OS | hosts 파일 수정하기

hosts 파일는 DNS보다 먼저 호스트명을 IP로 변경해 주는 파일이다. 주로 개발을 하거나, 특별한 이유로 호스트명으로 통신을 해야 하는 경우에 변경하여 사용할 있다.

터미널에서 편집기를 연다

hosts 파일을 수정하기 위해서는 관리자 권한이 필요하기에 sudo 명령어를 꼭 써줘야 한다.

$ sudo vi /etc/hosts

혹은

$ sudo vi /private/etc/hosts 

내용을 편집한다.

  1 ##
  2 # Host Database
  3 #
  4 # localhost is used to configure the loopback interface
  5 # when the system is booting.  Do not change this entry.
  6 ##
  7 127.0.0.1   localhost
  8 255.255.255.255 broadcasthost
  9 ::1             localhost
 10 fe80::1%lo0 localhost

아이피 주소를 넣고 구분은 탭(tab)으로 해야 한다.

127.0.0.1    www.devkuma.com

DNS cache 를 갱신한다.

이제 hosts 파일이 수정하면 재부팅하거나, dscacheutil -flushcache 를 입력하면 바로 적용 하실 수 있다.

$ dscacheutil -flushcache

3.9 - Mac OS | 사용중인 포트 찾아서, 종료시키기

아래와 같이 포트 번호를 넣고 프로세스를 검색한다.

lsof -i :{포트번호}

실제 검색을 하면 아래와 같이 나온다.

% lsof -i :8090
COMMAND   PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    62421 kimkc  409u  IPv6 0x891847b9306c0d75      0t0  TCP *:8090 (LISTEN)

그러면, 프로세스 아이디(PID)를 넣고 프로세스를 종료시키면 된다.

kill -9 {PID}

위에 검색한 프로세스 아이디(PID)는 62421 이다. 아래와 같이 명령어를 날리면 프로세스가 종료된다.

% kill -9 62421

3.10 - Mac OS | 터미널에서 VSCode를 실행하기

터미널에서 특정 디렉토리 디렉토리로 이동하여, 특정 파일을 열 수 있다.

$ code [File path]

설정 방법은 아래와 같다.

  1. Visual Studio Code 를 실행한다.
  2. Command Palette (⇧⌘P)를 누르면 멸령어 파레트가 열린다.
  3. ‘shell command’라고 쳐서 Shell Command: Install ‘code’ command in PATH command 를 찾은 후 실행한다.

3.11 - Mac OS | Maven 설치하기

설치하기

Homebrew를 사용한 메이블 설치명령어는 아래와 같다.

% brew install maven

위에 명령어를 실행하면 아래와 같이 표시되면서 설치가 된다.

Updating Homebrew...
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and adoptopenjdk/openjdk).
==> New Formulae
fabric-installer      gnupg@2.2             lefthook              lychee                revive                stp                   webhook
==> Updated Formulae
Updated 250 formulae.
==> Updated Casks
Updated 23 casks.

==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/manifests/15.0.2
######################################################################## 100.0%

... 가운데 생략 ...

For compilers to find openjdk you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk/include"

설치 확인하기

설치가 잘되었는지 버전확인 명령어로 확인할 수 있다.

% mvn -version

위와 같이 명령어를 입력하면 아래와 같이 결과가 표시되는 것을 확인할 수 있다.

Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
Maven home: /usr/local/Cellar/maven/3.8.1/libexec
Java version: 15.0.2, vendor: N/A, runtime: /usr/local/Cellar/openjdk/15.0.2/libexec/openjdk.jdk/Contents/Home
Default locale: ko_KR, platform encoding: UTF-8
OS name: "mac os x", version: "11.2.3", arch: "x86_64", family: "mac"
kimkc@kimkcui-MacBookPro macaront % 

설치 위치 확인

% which mvn
/usr/local/bin/mvn

3.12 - Mac OS | 터미널에서 디렉토리 및 파일에 색상 변경하기

~/.bash_profile 파일에 아래 내용을 추가한다.

export CLICOLOR=1
export LSCOLORS=GxFxCxDxBxegedabagaced

아래 명령어로 적용한다.

source ~/.bash_profile

참조

3.13 - Mac OS X Finder 숨은 폴더/파일 표시 방법

파인더에서 숨은 폴더/파일 표시하는 활성화/비활성화 방법

Command + Left Shift + .

3.14 - Mac OS 업데이트 이후에 발생하는 git xcrun error 해결 방법

xcrun error 에러 발생

Mac OS 업데이트를 한 이후로 git 명령어를 실행하니 아래와 같이 에러가 발생했다.

% git --version
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

찾아보니 Xcode Command Line Tools 관련해서 에러가 발생한 것으로 보인다.

해결 방법

XCode를 재설치하면 해결되나 전체설치가 필요하지 않는 경우에는 아래와 같이 콘솔에서 입력하여 Xcode Command Line Tools만 다시 설치하면 된다.

% xcode-select --install

명령어 라인 개발자 도구를 설치하겠습니까?라고 메시지 팝업이 표시되면 설치를 누른다. xcode-select &ndash;install

사용권 계약 팝업이 표시되면 동의를 누른다. xcode-select &ndash;install

소프트웨어 다운로드 화면이 나오고 한참동안 기다리다 보면, xcode-select &ndash;install

아래와 같이 설치 완료 화면이 표시된다. xcode-select &ndash;install

완료 버튼을 클릭하는 것으로 설치는 완료된다.

실행 확인

제대로 설치까지 완료가 되고 다시 git 명령어를 실행시켜 보면 에러가 발생하지 않는 것을 확인할 수 있다.

% git --version
git version 2.30.1 (Apple Git-130)

참고

4 - Docker 입문

Docker 입문

Docker는 심플하면서도 실용적인 기능을 갖고, 경량이라는 특징을 가진 가상 환경으로 애플리케이션 배치에서 빠르게 이용이 확산되고 있다. 필자도 최근에는 주로 개발 환경의 하나로서 적극적으로 이용하고 애플리케이션 배치를 쉽게 해주는 편리함을 통감하고 있다. 본 연재에서는 Docker에 관심이 있으면서도 아직 경험해 보지 못한 사람을 위해 실제로 실습해 보면서 Docker 대해 이해하기 위한 자료를 제공한다.

4.1 - Docker 입문 | 0. Docker

docker container ls

docker container ls 명령어을 실행했을 때 표시되는 항목에 대해 알아보도록 하자.

$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
2axaf8tx4gjd        registry            "/entrypoint.sh /etc…"   7 weeks ago         Up 7 weeks          0.0.0.0:5000->5000/tcp   devkuma-private-registry

실행중인 컨테이너 및 종료의 컨테이너를 표시하는 명령이다.

항목 내용
CONTAINER ID 컨테이너를 식별하기 위한 유일한 식별자
IMAGE 컨테이너를 만드는 데 사용한 Docker Image
COMMAND 컨테이너에서 실행되는 응용 프로그램 프로세스
CREATED 컨테이너 생성 후 후 경과 시간
STATUS Up (실행) Exited (종료) 등의 컨테이너의 실행 상태
PORTS 호스트 포트와 컨테이너 포트의 연결 관계 (포트 포 워 딩)
NAMES 컨테이너 이름

Dockerfile

Docker 이미지를 만들 때 반듯이 필요한 설정 파일이다. 이 파일에 작성된 지침을 인스트럭션(instruction) 이미지가 만들어진다.

기본적으로 Dcokerfile라는 이름을 사용하여 파일 이름을 변경하려면 Build시 추가 옵션을 주어야 한다. (-f)

인스트럭션(instruction)

FROM

  • 해당 Docker 이미지의 기본 이미지를 지정한다.

mysql을 지정하는 경우는 다음과 같다.

FROM mysql

COPY

  • 호스트 컴퓨터의 파일이나 디렉토리를 Docker 컨테이너에 복사한다.
  • 이미지가 Build 될 때 한 번만 실행된다.
COPY ./cnf/my.cnf /etc/mysql/conf.d/my.cnf

RUN

  • Docker 이미지를 Docker에서 실행하는 명령을 정의한다.
  • COPY와 마찬가지로 Build 될 때 한 번만 실행된다.
  • 특별한 지침이 없는 경우는 사용되지 않는다.

다음은 Test.java를 javac로 컴파일하고 있다.

RUN javac Test.java

ADD

기본은 COPY과 동일하며, 다음과 같은 기능이 추가로 있다.

  • source가 remote URL이면 다운로드 후 destination에 복사한다.
  • source가 자주 사용되고 있는 압축 파일 형식(zip 등)이면 압축을 풀어준다.
  • source가 remote URL + 압축 파일 형식인 경우 압축을 풀지 않는다.

CMD

  • 컨테이너에서 실행하는 프로세스 (명령)을 지정한다. 이것은 이미지를 실행할 때마다 실행되는 명령이다.
  • CMD는 Dockerfile에 하나만 만들 수 있다. 여러개를 만들 때 맨 마지막에있는 명령만 실행된다.

다음은 mysqld를 실행하고 있다.

CMD ["mysqld"]

4.2 - Docker 입문 | 61. Docker 이미지 컨테이너 관리 메커니즘

Docker는 심플하면서도 실용적인 기능을 제공하며, 경량형 가상 환경으로 애플리케이션 배포에 활용되어 빠르게 확산되어 이용되고 있다. 이 자료는 Docker에 관심이 있으면서도 아직 경험해 보지 못한 사람을 위해 실제로 실습을 해보면서 Docker를 이해하기 위한 자료를 제공한다. 이번 장에서는 Docker 개요 및 가장 기본인 이미지와 컨테이너 관리에 대한 실제 조작 방법을 단계별로 소개한다.

Docker는?

Docker는 Linux 컨테이너 기술을 기반으로 Docker 사가 개발한 가상화 기술이다. 여기에서는 Docker 자체에 대해 간략하게 설명한다. 자세한 설명은 Docker 공식 문서를 참조하길 바란다.

  • Docker는 컨테이너 기반의 가상화 기술이다.
  • 기존에는 OS를 가상화 하였기 때문에 Host OS 위에 Guest OS를 설치해야 했다. 이런한 방식은 상당히 무겁고 느려서 한계가 많이 있다.
  • 그래서 이를 극복하고자 프로세스를 격리시킨 컨테이너를 통해 가상화를 하는 Docker(도커)와 같은 기술들이 등장하게 되었다.
  • 도커를 통해 구동되는 컨테이너를 관리하기 위한 Kubernates(쿠버네티스)가 등장하게 되었다.

Docker의 특징

(1) 경량

첫번째 특징은 다운로드 및 실행이 매우 가볍다는 것이다.

VirtualBox 등 기존의 하이퍼 바이저 가상 머신(아래 왼쪽)는 호스트 OS에서 하이퍼 바이저라는 소프트웨어는 가상 머신을 생성하고 그 위에 게스트 OS를 가동시키는 방식이다. 호스트 OS와 게스트 OS를 분리 할 수 있다는 장점이 있지만, 게스트 OS와 가상 머신의 분, 이미지 크기가 커지고 오버 헤드가 증가한만큼 동작도 느려진다.

한편 Docker가 채용하고있는 컨테이너(주 1)(아래 오른쪽)에서 각 응용 프로그램은 Linux 컨테이너 기술은 호스트 OS의 커널은 공유하면서도 각 컨테이너 응용 프로그램은 분리된 네임스페이스 중간에서 실행된다. 그림의 Docker Engine은 가상 머신과 커널의 에뮬레이션도 없기 때문에 이미지 크기도 작고, 베어 메탈(BareMetal)에 가까운 수준으로 가볍고 작동한다.

‘베어메탈(Bare Metal)’이란 용어는 원래 하드웨어 상에 어떤 소프트웨어도 설치되어 있지 않은 상태를 뜻한다. 즉, 베어메탈 서버는 가상화를 위한 하이퍼바이저 OS 없이 물리 서버를 그대로 제공하는 것을 말한다. 따라서 하드웨어에 대한 직접 제어 및 OS 설정까지 가능하다.

(주 1) 컨테이너는 Docker 이미지를 기동하고 그 내부에서 응용 프로그램이 실행중인 상태.

하이퍼 바이저 형의 차이점

또한, 여러 이미지 데이터를 공통화하여 데이터 크기를 줄일 연구도 하고 있다. 구체적으로는, 컨테이너 자체의 여러 계층으로 구성되어 컨테이너 작업(패키지의 설치이거나 파일의 작성 등)은 각 레이어에서 이루어 진다. 이 계층 구조에 따라 이미지를 가져 오거나 가져올 때 레이어의 차이만 처리하면 잘된다. 따라서 다루는 이미지 데이터의 양이 줄어어 동작이 가볍다.

예를 들어, 아래 그림 중의 AppB과 AppC 컨테이너는 그림 오른쪽처럼 3개의 층으로 구성되어 있다. AppB과 AppC는 2층(Layer2)까지 공통의 조작으로 컨테이너가 생성되어 있기 때문에, 2층까지 일반화되어 있다. 따라서 먼저 AppB의 이미지를 올리고 나서, AppC의 이미지를 올릴 때는 3층(Layer3)만 올리며 된다. 이는 새로 올리는 이미지 데이터 양과 Docker Engine이 읽어들이는 데이터 량의 감소로 이어지게 된다.

이미지 계층화

(위 그림은 " Digital Ocean - The Docker Ecosystem : An Introduction to Common Components“에서 인용)

(2) 풍부한 에코 시스템 : 다양한 환경에 배포할 수 있다.

Docker은 원래는 Docker 사가 개발 한 가상화 기술이지만, 현재는 마이크로소프트와 인텔, 레드햇, Google, AWS 등 많은 업체들이 발족한 ‘Open Container Initiative’를 통해 업계 통일 사양으로 구성되어 있습니다. 많은 PaaS를 지원함으로써 표준 응용 프로그램 배포 방법으로 정착하고 있습니다.

주요 OS로 Linux, Windows, Mac 및 주요 PaaS 인 AWS , Google Cloud , Azure 가 Docker를 지원한다(주 3). 일단 한번 응용 프로그램을 Docker 컨테이너의 이미지로 만들면 그대로 다양한 플랫폼에서 실행할 수 있는 환경이 정비되어 왔다. 이렇게 되면 응용 프로그램 배포 수단으로 Docker 이미지를 활용하는 움직임이 활발 해 지고 있다. 플랫폼 별 환경 구축의 수고를 덜 수 있으며, 응용 프로그램 개발 자체에 좀 더 집중할 수 있게 된다.

(주 3) Windows, Mac의 경우는 호스트 OS에서 하이퍼 바이저 형의 가상 머신을 시작해 그 게스트 OS에 Docker Engine을 이동하는 구성으로 되어 있다. Linux가 아닌 경우 Docker 경량이라는 장점 완전히 누릴 수 없는 점에 주의하시기 바란다.

(3) 충실한 툴

API와 툴을 갖추고 있는 것도 Docker의 큰 장점이다. 실용적인 용도를 망라한 다음과 같은 다양한 툴들을 무료로 사용할 수 있다. 처음 접하면 여러가지 있어 어렵게 느끼질 수도 있지만, 하나씩 사용해 가면 익숙해져 가보록 하자.

  • Docker Engine
    • Docker 컨테이너 이미지를 실행 관리 서버 및 조작 CLI(Command Line Interface)를 포함한다. v1.12.0에서 클러스터 관리 기능도 통합되었다.
  • Docker Compose
    • 여러 컨테이너를 실행하고 관리하기위한 도구.
  • Docker Registry
    • 이미지를 저장하거나 배포할 수 있는 서버 소프트웨어.

또한, 이미지 관리용 서버인 Docker Registry는 이용 인원수가 늘어나면 분산 부하 및 데이터 백업 등을 고려할 필요해 진다. 그런 상황에서는 다음과 같은 옵션을 사용할 수 있다.

  • Docker Hub
    • Docker 사가 운영하는 PaaS 버전 Docker Registry. 무료로 사용할 수 있다.
    • 오픈소스 소프트웨어(Open Source Software, OSS) 커뮤니티처럼 이미지를 게시 할 수 있는 프로젝트에 적합하다.
  • Docker Trusted Registry
    • 상용 지원용 On-premises software에 해당하는 Docker Registry.
    • 사내 같은 닫힌 사회에서 Docker 이미지를 배포하는 경우에 좋다.

Docker의 장단점

  • 장점
    • 쉽고 빠르게 실행 환경을 구축할 수 있다.
    • 하드웨어 자원이 절감된다.
    • Docker Hub와 같은 공유 환경을 제공한다.
  • 단점
    • 개발 초기의 오버헤드가 발생한다.
    • Linux 친화적이다.

Docker 실습

지금까지 Docker 자체에 대한 설명을 하였다. Docker를 제대로 이해하려면 직접 동작을 해보는 것이 가장 좋을 것이다. 꼭 한번 대충 실습을 해보길 권장한다.

Docker Engine 설치

우선 Docker를 설치하자. Docker 주요 OS (Linux, Windows, Mac)을 지원하고 있다. 사용자의 환경에 맞는 방법으로 설치하도록 하자.

Linux에 설치

배포판마다 설치 방법이 다릅니다. 공식 문서에서 리눅스 배포본의 설치 방법을 참조하길 바란다.

Windows에 설치

Windows 버전에 따라 설치 방법이 다르다. 각각 설치 프로그램을 실행하면 설치할 수 있다.

  • Microsoft Windows 10 Professional 또는 Enterprise 64-bit에서는 Docker CE for Windows를 설치할 수 있다.
  • 그외에 Docker Toolbox라는 도구가 제공되고 있다.

(주) Docker Ver. 1.12.0에서 Hyper-V(Windows 8 이상을 지원하는 하이퍼 바이저 가상 환경)를 지원한다. Windows 10에서는 OS가 제공하는 하이퍼 바이저 형의 가상 머신 위에서 Docker를 이용할 수 있게 되었다. 그 이전에는 Docker Toolbox하여 VirtualBox에서 Linux에 Docker Engine을 설치하고 호스트의 커멘드 라인 도구에서 액세스하는 방식으로 해야만 했다.

Mac OS에 설치

OS X Yosemite 10.10.3 이후에는 Docker CE for Mac 을 설치할 수 있다. 그 이전에는 Docker Toolbox라는 도구가 제공하고 있다.

(주) Docker Ver. 1.12.0에서 HyperKit (OS X Yosemite 이상을 지원하는 하이퍼 바이저 가상 환경)를 지원한다. 이는 OS X 10.10 Yosemite 이상에서는 OS가 제공하는 하이퍼 바이저 형의 가상 머신 위에서 Docker를 이용할 수 있게 되었다. 그 이전에는 Windows 8 이전과 마찬가지로 Docker Toolbox를 사용한다.

이 자료에서의 실행 환경

이 자료에서는 다음과 같은 환경에서 본 기사의 샘플을 테스트하였다.

  • Linux
    • OS : Ubuntu Server 16.04 LTS
    • 인스턴스 유형 : m4.large
    • Docker : 17.03.1-ce
  • Mac
    • OS : Mac OS 11.4 (Big Sur)
    • CPU : 2.3 GHz 8 Core Intel Core i9
    • 메모리 : 16 GB
    • Docker : 17.04.0-ce (Docker for Mac)
  • Windows
    • OS : Windows 7 64bit
    • CPU : Intel Core i3-3120M CPU 2.50GHz 2.50Hz
    • 메모리 : 16 GB
    • Docker : 17.04.0-ce (Docker Toolbox)

설치 테스트

설치가 되었다면 다음 명령으로 데몬이 실행되는지 확인한다. 표시가 되지 않았따면 설치에 실패한 것이다. 다시 문서를 참조하길 바란다.

% docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Hello World를 표시해 보자.

설치가 되 프로그래머에게 익숙한 hello world를 해 봅시다.

% docker run hello-world

docker run는 이미지에서 컨테이너를 시작하는 명령어이다. 위 명령어는 hello-world 라는 이미지로 부터 컨테이너를 시작한다는 의미이다. 그러나 로컬에 hello-world 이미지가 없기 때문에, Docker 데몬이 hello-world 이미지를 Docker Hub(Docker 사가 운영하는 PaaS 형의 Docker Registry)에서 다운로드하여 이미지의 컨테이너를 시작한다. 이 컨테이너는 다음과 같이 표준 출력을 하고 종료된다.

Unable to find image 'hello:latest' locally
docker: Error response from daemon: pull access denied for hello, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.
kimkc@kimkcui-MacBookPro macaront-core % docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

컨테이너에 Linux를 동작 시켜보자.

앞에서 hello-world 예제에서는 명령 라인에서 이미지 수집과 컨테이너 시작을 쉽게 할 수 있다는 것을 확인하였다.

다음은 좀 더 복잡한 예를 들어, Alpine Linux라는 컨테이너 용으로 개발된 경량 Linux 배포판의 컨테이너를 조작하는 방법을 소개한다. 이 튜토리얼을 통해 Docker를 사용하는데 있어서 가장 기본이 되는 다음 사항을 배울 수 있다.

  • 이미지 가져 오기 (pull)
  • 이미지의 나열 (images)
  • 컨테이너의 라이프 사이클 관리
    • 생성(create)
    • 시작(start)
    • 정지(stop)
    • 삭제(rm)
  • 컨테이너의 표시 (ps)

우선 alpine의 이미지를 받아 오자. 이미지를 받아 오려면 pull 명령을 사용한다.

% docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
5843afab3874: Pull complete
Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest

images 명령어으로 받은 이미지 목록을 확인할 수 있다. 앞에서 hello world와 alpine의 이미지가 표시되고 있는 것을 확인할 수 있다.

% docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
alpine        latest    d4ff818577bc   26 hours ago   5.6MB
hello-world   latest    d1165f221234   3 months ago   13.3kB

그럼, 다음 alpine 이미지에서 컨테이너를 시작해 보자. 컨테이너의 시작은 run 명령어를 사용한다.

명령어 문법은 아래와 같다.

`docker run <이미지 이름> <컨테이너에서 시작하는 명령>`

run는 컨테이너를 생성(create)하고, 그 컨테이너를 시작(start)까지 진행한다. 고급 옵션은 Docker 공식 문서를 참조하길 바란다.

% docker run alpine echo "hello from alpine"
hello from alpine

<컨테이너에서 시작하는 명령>으로 echo 명령을 지정했기에 컨테이너를 시작한 직후에 echo 명령을 실행하고 컨테이너는 종료되었다.

지금까지는 컨테이너 시작할 때 1개만 명령을 실행하고, 바로 종료가 되었는데, 컨테이너에서 대화형 명령 작업을 하고 싶은 경우에는 run 명령에 옵션 -it을 붙여 컨테이너에 연결을 해보록 하자. 다음 예제의 경우는 컨테이너를 기동하고 쉘이 실행되었기에 컨테이너에서 Linux 명령을 사용할 수 있게 되었다.

% docker run -it alpine bin/sh
/ # ls
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

그리고 1개의 터미널을 더 열어서 ps 명령을 실행하여 보자. ps 명령은 현재 실행중인 컨테이너를 확인하는 명령이다. 현재 또 하나의 터미널에서 alpine 이미지에서 컨테이너를 시작하고 bin / sh 명령을 실행하는 것을 알 수 있습니다.

% docker ps
CONTAINER ID   IMAGE     COMMAND    CREATED          STATUS          PORTS     NAMES
d0736179149d   alpine    "bin/sh"   56 seconds ago   Up 55 seconds             nifty_keller

여기서 stop 명령을 실행하면, 컨테이너를 중지할 수 있다. 위에 alpine 컨테이너를 기동한 터미널을 열어서, 컨테이너가 정지하고 있는 것을 확인 할 수 있다.

% docker stop d0736179149d
d0736179149d

stop은 컨테이너를 종료하는 것은 아니고, 어디까지나 중지할 뿐이다. 중지한 컨테이너를 start 명령으로 다시 시작할 수 있다. ps 명령 컨테이너가 실제로 시작되고 있는지 확인한다.

% docker start d0736179149d
d0736179149d
% docker ps
CONTAINER ID   IMAGE     COMMAND    CREATED         STATUS          PORTS     NAMES
d0736179149d   alpine    "bin/sh"   5 minutes ago   Up 13 seconds             nifty_keller

그러나 이대로는 다시 컨테이너를 조작할 수 없다. 터미널에서 컨테이너에 연결하려면 attach 명령을 사용한다. 인자는 컨테이너 ID이다.

% docker attach d0736179149d
/ # ls
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var
/ #

컨테이너를 종료(정지 + 삭제)하려면 컨테이너에 연결한 상태에서 exit 명령어로 실행한다. (윈도우 Ctrl+C으로 가능하다.)

/ # exit

또는 stop 명령으로 정지시키고, rm 명령으로 컨테이너를 제거할 수 있다.

% docker stop 30cf0829bee2
30cf0829bee2
% docker rm 30cf0829bee2
30cf0829bee2

일단 컨테이너를 삭제하면 해당 컨테이너를 start 명령으로 재기동 할 수 없다.

% docker start 30cf0829bee2
Error response from daemon: No such container: 30cf0829bee2
Error: failed to start containers: 30cf0829bee2

컨테이너에서 Web 서버를 움직여 본다

지금까지 Alpine Linux의 이미지를 예로 이미지 및 컨테이너 관리 방법에 대해 설명하였다.

다음은 마지막 예로, 좀 더 실용적으로 Docker에 의해 Web 서버의 배포를 소개해 보도록 하겠다.

여기에서는 seqvence/static-site라는 Docker Hub 에서 공개된 이미지를 사용한다. 이 이미지의 컨테이너 내부에서는 Nginx(Web 서버)가 포함되어 있고, 액세스할 수 있는 Web 브라우저에 컨테이너내의 정적 Web 페이지 를 제공한다. Docker는 게스트 측의 포트를 호스트 측에 매핑시킬 수 있기에, Web 브라우저에 의한 호스트 포트에 대한 액세스를 게스트로 전송할 수 있다. 이렇게 하여 Docker에 Web 서버를 시작하여 Web 어플리케이션을 제공할 수 있다.

우선 컨테이너를 시작해 봅자. “Your Name"부분은 적당한 이름을 넣는다.

% docker run --name static-site -e AUTHOR="Docker" -d -p 80:80 seqvence/static-site
Unable to find image 'seqvence/static-site:latest' locally
latest: Pulling from seqvence/static-site
Image docker.io/seqvence/static-site:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
fdd5d7827f33: Pull complete
a3ed95caeb02: Pull complete
716f7a5f3082: Pull complete
7b10f03a0309: Pull complete
aff3ab7e9c39: Pull complete
Digest: sha256:41b286105f913fb7a5fbdce28d48bc80f1c77e3c4ce1b8280f28129ae0e94e9e
Status: Downloaded newer image for seqvence/static-site:latest
9277612d90a1c6eb434c976db6bd6f1e1c651b05c0c35b1cc053656f53544ba1

처음 시작하게 되면 위와 같이 이미지 다운로드가 진행되고, 도커가 실행되거 있다는 것을 아래와 같이 확인할 수 있다.

% docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                                        NAMES
9277612d90a1   seqvence/static-site   "/bin/sh -c 'cd /usr…"   54 seconds ago   Up 52 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 443/tcp   static-site

위의 명령 옵션은 다음과 같다.

옵션 의미
-name static-site 컨테이너 이름으로 static-site를 지정한다.
-e AUTHOR=“Docker” 컨테이너에 환경 변수 Author 며 “Docker"를 건네준다. 이 컨테이너는 환경 변수 Author를 Web 페이지를 표시하는 데 사용하고있다.
-d Detach mode(분리 모드)로 부팅 (컨테이너가 데몬으로 백그라운드로 시작한다.)
-p 80:80 컨테이너의 개방된 포트(80)를 호스트 포트(80)에 할당한다.

위의 경우 게스트의 80번 포트를 호스트의 80번 포트에 할당하였기에 브라우저로 80번 포트에 액세스하면 Docker 컨테이너에서 Web 응용 프로그램이 생성한 Web 페이지가 표시되게 된다.

static-site의 실행 결과

(주) 사용하는 Docker Engine을 통해 액세스할 URI가 다르다.

  • Linux, Docker for Windows(Windows 10 이상), Docker for Mac (OS X 10.10 Yosemite 이상)의 경우 localhost:80에서 결과를 확인할 수 있다.
  • 그 외에는 docker-machine ip default로 Docker 데몬의 IP 주소를 확인하도록 한다.

그러면, -p 옵션을 변경하여, 호스트 측의 다른 포트에 할당할 수 있다. 다음의 경우는 두번째 컨테이너를 시작하여 게스트 측의 80 포트를 호스트의 8080 포트에 할당한다. 따라서 Web 브라우저에서 localhost:8080에 액세스하여 Web 페이지를 표시되게 할 수 있다.

% docker run --name static-site2 -e AUTHOR="My second Docker" -d -p 8080:80 seqvence/static-site
8996b832b603037d37e7d32c456fdc259929fe0a9094968ad2762c0c9651db3b

이것으로 간단한 예제를 사용하여 호스트에서 Docker 컨테이너의 Web 서버에 액세스되는 것을 확인하였다. 방화벽 설정(Linux에서는 iptables)를 변경하고 외부에서 호스트의 HTTP 포트에 액세스 가능하면 Docker의 Web 서버를 외부에 공개 할 수 있다.

이를 응용하여 클라우드 서버에 Docker를 설치하여 두면 Docker 명령에서 이미지 검색에서 컨테이너의 Web 서버 시작까지를 포함한 배포 작업을 쉽게 할 수 있다. 또한 Web 페이지의 내용을 간단히 변경하여, 호스트 측에서 다시 새로운 Docker 이미지를 가져와 컨테이너를 시작한 것으로 가능한 것을 확인 하였다.

정리

여기서는 Docker 개요 기존 이미지 및 컨테이너 작업 방법을 설명하였다. Web 서버를 배포하는 방법에 대해서도 소개하였다. 이번에서는 이미지 및 컨테이너 관리는 어렵지 않게 응용 프로그램의 배포도 쉽게 할 수 이해했을 것으로 생각된다. 그러나 실제로 Docker에서 응용 프로그램을 배포하는데 자신의 이미지를 작성하고 배포해야 한다. 다음에는 이미지를 만드는 방법 소개하겠다.

4.3 - Docker 입문 | 2. Docker 이미지 빌드

앞에서는 Docker 개요 및 가장 기본 인 이미지와 컨테이너 관리에 대한 실제 조작 방법을 단계별로 소개하였다. 지금까지는 공개된 이미지를 이용했지만, 스스로 개발하고 있는 응용 프로그램을 Docker 이미지로 배포하기 위해서는 스스로 이미지를 만들 수도 있어야 한다. 그래서 이번에는 직접 이미지를 생성하고 컨테이너를 시작하는 방법을 소개하겠다. 또한 여기서에서 소개하는 샘플은 Docker 사가 공개하고 있는 초보자를 위한 튜토리얼의 내용을 기반으로 하고 있다.

Docker 이미지 빌드 구조

먼저 Docker 이미지를 만드는 방법을 대해 소개한다.

Docker 이미지 빌드는 기반이 되는 이미지에 어떤 기능을 추가하여 사용자 이미지(자신만의 이미지)을 일으키는 것을 말한다.

빌드 구조

기반 이미지는 일반적으로 Docker 사 또는 Docker 커뮤니티가 제공하는 OS의 이미지가 되는 경우가 많다. 이미지에 다양한 의존 라이브러리와 미들웨어를 설치하거나 자신의 응용 프로그램을 설치 및 구성하거나 하여 사용자 이미지를 만든다. 이 사용자 이미지를 제 3자에게 배포하여 라이브러리 미들웨어 애플리케이션 등을 모두 포함하는 형태로 배포 할 수 있다.

이 때 기본 이미지에 대해 수행할 작업을 설명하는 설정 파일은 “Dockerfile"이다. Dockerfile는 Docker 사에 의해 작성 방법이 규정되어 있다. 자세한 내용은 문서를 참조하라.

샘플 이미지 빌드

여기에서는 flask라는 Python 용 Web 어플리케이션 프레임워크를 사용한 Web 응용 프로그램을 배포하는 Docker 이미지를 구축해 보도록 한다. 응용 프로그램은 무작위로 고양이의 GIF 이미지를 표시하는 것이다. flask 자체의 상세한 설명은 여기서는 생략하겠다.

빌드에 필요한 파일 준비

디렉토리를 작성하고 다음과 같이 이미지의 빌드에 필요한 4개의 파일을 받아온다.

% mkdir flask-app
% cd flask-app
% wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/app.py
% wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/requirements.txt
% wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/templates/index.html -P templates
% wget https://raw.githubusercontent.com/docker/labs/master/beginner/flask-app/Dockerfile

그런 다음에는 각 파일의 내용을 소개하겠다.

app.py 파일은 Web 어플리케이션의 엔트리 포인트가 되는 소스 코드이다. Web에서 GIF 이미지를 검색하여 무작위로 URL을 반환하는 작업을 수행한다.

from flask import Flask, render_template
import random

app = Flask(__name__)

# list of cat images
images = [
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-26388-1381844103-11.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-31540-1381844535-8.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-26390-1381844163-18.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-1376-1381846217-0.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-3391-1381844336-26.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-29111-1381845968-0.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-3409-1381844582-13.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-19667-1381844937-10.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-26358-1381845043-13.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-18774-1381844645-6.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-25158-1381844793-0.gif",
    "https://raw.githubusercontent.com/devkuma/docker-tutorial/main/flask-app/image/anigif_enhanced-buzz-11980-1381846269-1.gif"
]

@app.route('/')
def index():
    url = random.choice(images)
    return render_template('index.html', url=url)

if __name__ == "__main__":
    app.run(host="0.0.0.0")

requirements.txt 파일는 필요한 Python 모듈 기입한 파일이다. pip(패키지 관리자)를 사용하여 flask를 설치할 때 사용한다.

Flask==1.0

templates/index.html 파일는 Web 응용 프로그램에서 출력하는 HTML 템플릿이다. 고양이 이미지의 표시만한다.

<html>
  <head>
    <style type="text/css">
      body {
        background: black;
        color: white;
      }
      div.container {
        max-width: 500px;
        margin: 100px auto;
        border: 20px solid white;
        padding: 10px;
        text-align: center;
      }
      h4 {
        text-transform: uppercase;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h4>Cat Gif of the day</h4>
      <img src="{{url}}" />
      <p><small>Courtesy: <a href="http://www.catshaming.co.uk/20-best-cat-gif-posts">Catshaming</a></small></p>
    </div>
  </body>
</html>

Dockerfile는 Docker 데몬이 이미지를 만들 때 사용하는 명령어를 정리한 파일이다. 샘플 Dockerfile에서는 다음과 같은 내용의 처리를 실행하고 있다. Dockerfile의 문법에 대해서는 뒤에서 설명하겠다.

  • 기본 이미지로 Alpine Linux (Docker 용으로 개발 된 경량 Linux 배포판)을 지정한다.
  • Python과 pip (패키지 관리자)를 설치한다.
  • pip에서 응용 프로그램에 필요한 Python 모듈을 설치한다.
  • app.pyindex.html을 정해진 위치에 복사한다.
  • 포트 5000 번을 외부에 공개한다.
  • Web 응용 프로그램을 실행한다.
# our base image
FROM alpine:3.5

# Install python and pip
RUN apk add --update py2-pip

# upgrade pip
RUN pip install --upgrade pip

# install Python modules needed by the Python app
COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt

# copy files required for the app to run
COPY app.py /usr/src/app/
COPY templates/index.html /usr/src/app/templates/

# tell the port number the container should expose
EXPOSE 5000

# run the application
CMD ["python", "/usr/src/app/app.py"]

(보충) Dockerfile에서 사용되는 명령

Dockerfile를 보면, 처음에는 shell 스크립트처럼 보이지만 실제로는 Dockerfile 특유의 명령이 사용되고 있다. 샘플 Dockerfile에서 사용되는 명령은 다음 표에 나와 있다. 문법의 자세한 내용은 매뉴얼에 기재되어 있으므로 참조해 하길 바란다.

명령 의미 보충
FROM 기본 이미지가되는 이미지 지정
RUN 이미지를 빌드하기위한 명령을 지정 RUN apk add -update py-pip의 경우, 실제로는 apk add -update py-pip 부분이 실행된다.
COPY 호스트에서 컨테이너에 파일을 복사한다.
EXPOSE 외부에 공개하는 컨테이너 포트를 지정한다. 기본적으로 컨테이너 포트가 닫혀있다.
CMD 이미지에서 컨테이너를 시작할 때 실행할 명령을 지정한다. Dockerfile에서 CMD는 1 개만 지정할 수 있다.

그밖에 Dockerfile 작성 모범 사례에 대해서는 Best practices for writing Dockerfiles에 정리하고 있어, 이쪽도 참조해 보길 바란다.

이미지 빌드

Docker 데몬이 실행되고 있지 않으면 빌드 할 수 없습니다. 미리 데몬을 시작하십시오.

현재 디렉토리에 Dockerfile가있는 상황에서 다음 명령을 실행하십시오. Dockerfile의 내용이 순서대로 실행되는 것을 알 수 있다고 생각합니다.

(주) 샘플 프록시 설정은 준비되어 있지 않아서 HTTP 프록시가 없는 환경에서 실행해야 한다.

% docker build -t myfirstapp .
Sending build context to Docker daemon  8.192kB
Error response from daemon: dial unix docker.raw.sock: connect: connection refused
kimkc@kimkcui-MacBookPro flask-app % docker build -t myfirstapp .
[+] Building 16.1s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                 0.0s
 => => transferring dockerfile: 571B                                                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/alpine:3.5                                                                                        4.1s
 => [internal] load build context                                                                                                                    0.0s
 => => transferring context: 2.46kB                                                                                                                  0.0s
 => [1/7] FROM docker.io/library/alpine:3.5@sha256:66952b313e51c3bd1987d7c4ddf5dba9bc0fb6e524eed2448fa660246b3e76ec                                  0.5s
 => => resolve docker.io/library/alpine:3.5@sha256:66952b313e51c3bd1987d7c4ddf5dba9bc0fb6e524eed2448fa660246b3e76ec                                  0.0s
 => => sha256:66952b313e51c3bd1987d7c4ddf5dba9bc0fb6e524eed2448fa660246b3e76ec 433B / 433B                                                           0.0s
 => => sha256:f7d2b5725685826823bc6b154c0de02832e5e6daf7dc25a00ab00f1158fabfc8 528B / 528B                                                           0.0s
 => => sha256:f80194ae2e0ccf0f098baa6b981396dfbffb16e6476164af72158577a7de2dd9 1.51kB / 1.51kB                                                       0.0s
 => => sha256:8cae0e1ac61cead281f41115cc0ebd39117f7e54dffc8fd5e05a7590dca3cd4e 1.97MB / 1.97MB                                                       0.3s
 => => extracting sha256:8cae0e1ac61cead281f41115cc0ebd39117f7e54dffc8fd5e05a7590dca3cd4e                                                            0.2s
 => [2/7] RUN apk add --update py2-pip                                                                                                               4.9s
 => [3/7] RUN pip install --upgrade pip                                                                                                              2.8s
 => [4/7] COPY requirements.txt /usr/src/app/                                                                                                        0.0s
 => [5/7] RUN pip install --no-cache-dir -r /usr/src/app/requirements.txt                                                                            3.0s
 => [6/7] COPY app.py /usr/src/app/                                                                                                                  0.0s
 => [7/7] COPY templates/index.html /usr/src/app/templates/                                                                                          0.0s
 => exporting to image                                                                                                                               0.7s
 => => exporting layers                                                                                                                              0.7s
 => => writing image sha256:b012c41a03101ad398f22ed50e569d3b5277f608847ca3275a555d6d21babf0c                                                         0.0s
 => => naming to docker.io/library/myfirstapp                                                                                                        0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

컨테이너의 시작

이미지 빌드가 완료되면 다음 명령으로 이미지에서 컨테이너를 시작한다.

% docker run -p 8888:5000 --name myfirstapp myfirstapp
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

위 명령의 경우 옵션은 컨테이너의 포트 5000 번을 호스트의 8888 번으로 지정하고 있다. Web 브라우저를 열고 http://localhost:8888에 액세스해 보면, 앞에서 소개한 Web 응용 프로그램이 표시될 것이다.

컨테이너의 정지 · 삭제

시작 컨테이너를 중지하려면 다음 명령을 실행한다

% docker stop myfirstapp

그리고, 정지한 컨테이너를 삭제하려면 다음 명령을 실행한다.

% docker rm myfirstapp

정리

여기에서는 구체적인 예제 응용 프로그램을 통해 Dockerfile을 사용하여 이미지를 빌드하여 이미지의 컨테이너를 시작하는 방법을 소개하였다. 이번에는 이미지 빌드의 기초적인 부분은 커버하고 있어 이미지 빌드 요약 파악하고 받을 수 있었다. Docker의 공식 문서에 매우 충실하게 되어 있기에 해당 도큐먼트도 함께 참조하면 다양한 경우에도 대응할 수 있을 것이다.

이번에는 로컬에서 빌드 로컬에서 컨테이너를 시작하는 작업을 실시하였지만 본인 외에 다른 사람에게 이미지를 이용할 수 있도록 하기 위해서는 이미지를 제 3자가 이용할 수 있는 형태로 공개해야 한다. 다음은 이미지의 공개 방법을 소개하겠다.

4.4 - Docker 입문 | 3. Docker 이미지 관리

앞에서 Dockerfile에서 이미지를 빌드하는 방법을 소개하였다. 로컬에서 빌드한 이미지는 Docker Engine에 캐시되어 있을 뿐이고 다른 사람은 사용할 수 없다. 이미지를 다른 사람이 사용할 수 있게 하려면, 이용자가 접근 할 수 있는 위치에 이미지를 공개해야 한다. Docker 회사나 AWS를 비롯한 각종 클라우드 벤더는 Docker 이미지를 관리하고 공유하는 구조로, “레지스트리"라는 서비스를 제공하고 있다. 이번에는 Docker 이미지의 레지스트리로 Docker Hub 및 AWS ECR (EC2 Container Registry)의 개요, 간단한 이미지 등록 · 취득 방법 및 팀 내에서 이미지를 관리 할 때 고려해야 할 사항에 대해 소개한다.

레지스트리에 이미지를 공유

첫째, 팀의 이미지 관리 방식에 대한 개요를 이해하기 위해, 벤더 중립적인 수준에서의 리지스토리의 개요를 소개한다. 개별 서비스에 의존하는 부분에 대해서는 서비스 별 섹션에서 설명한다.

레지스트리는 팀에서 이미지를 관리 · 공유하기 위해 주로 두 가지 역할을 제공한다.

  • 이미지 등록 및 공유
    • 이미지 저장소로 이미지를 등록 할 수 있다.
    • 다른 이용자에게 이미지를 공개 할 수 있다.
  • 이미지에 대한 액세스 제한 (인증 · 허가)
    • 특정 사람에게만 이미지의 읽기 및 쓰기를 허용한다. 다음은 레지스트리 서비스의 개념도이다.

저장소

  • “레지스트리"는 이미지를 등록하는 서비스 전체를 말한다.
  • 레지스트리에 게시할 이미지(Nginx와 Node.js 등)의 범주에 대해 “저장소"가 실제 이미지 저장소에 등록된다.
  • 저장소에 이미지를 복수 등록할 수 있고, 각 이미지는 태그로 구분된다. 버전 번호별로 이미지를 구별하고 싶은 경우 등에는 태그에 버전 번호를 지정한다. 예를 들어, Docker 공식 Node.js 이미지의 경우, 14.17.1 및 14.17.1-alpine 등으로 Node.js의 버전 번호와 Linux 배포판 등 이미지의 내용을 태그로 표현하고 있다.
    • 주의: 태그가 동일한 이미지는 덮어 쓰기버리기 때문에 저장소에 이미지를 push 할 때는 주의가 필요한다.
  • 먼저 레지스트리에 액세스 할 때 인증이 필요하다. 또한 push 및 pull 등 저장소에 대한 작업에 대한 사용자별로 접근 권한을 설정할 수 있다. 따라서 이미지를 관리하는 사람에게는 저장소에 push 권한을 부여하여 이미지를 이용하는 사람은 pull 권한을 부여하는 것이 가능하다.

Docker Hub - Docker 회사의 공식 레지스트리

다음 개별 레지스트리에 대해 설명한다. 먼저 Docker 회사가 클라우드 서비스로 제공하는 Docker Hub 을 소개한다.

Docker Hub이란?

Docker Hub는 Docker 회사가 제공하는 이미지 관리용 클라우드 서비스이다. 특징은 다음과 같다.

  • 완전 관리형
    • Docker 회사에서 관리하는 클라우드 서비스를 이고, 이를 사용하면 직접 서버를 관리할 필요가 없어진다.
  • Web UI
    • 이미지와 Docker Hub 계정 관리를 브라우저에서 할 수 있다.
  • 메타 데이터 저장소
    • 사용자 간의 의사 소통 지원을 위한 저장소에 댓글을 달거나, 스타(Facebook의 “좋아요"에 해당)을 줄 수 있다.
  • 인증 · 인가
    • 저장소에 액세스하는 다른 사용자에게 이미지의 읽기 · 쓰기 · 관리 등의 액세스 제한을 걸 수 있다.
  • 팀에서의 저장소 공유 · 관리
    • 팀에서 저장소를 공유하고 공동으로 관리 할 수 있다.
  • Webhook
    • CI/CD 환경과 연동하기 위한 Webhook을 제공한다.

Docker Hub에 이미지를 push/pull 해 보자

여기에서 실제로 공개 저장소를 만들고 해당 저장소에 이미지를 push해 보록 하자. 앞전에 빌드한 이미지를 이용할 것이기에, “Docker 이미지 빌드” 연습을 실시하지 않았다면, 먼저 실습을 하고 오길 바란다.

리포지토리 만들기

저장소를 작성하려면 Docker Hub 계정이 필요한다. Docker Hub에 접속하여 사전에 계정을 만들어야 한다.
(Docker Hub에 가입을 하면, 이메일 주소로 인증을 진행하게 된다. 인증이 완료되어야 계정 생성이 최종 완료된 것이다.)

다음 Docker Hub에 로그인 후 화면에서 “Create Repository"를 클릭하여 리포지토리 생성 화면을 표시한다. 저장소 이름은 이미지와 같은 “myfirstapp"를 지정한다. Visibility는 “public (공개)“로 해도 괜찮다.

저장소 생성

레지스트리 인증하기

저장소에 이미지를 push하기 전에 레지스트리를 인증해야 한다. username과 password를 입력하라는 메시지가 나오면, Docker Hub에 가입한 대로 입력하면 된다. Login Succeeded라고 표시되면 로그인 성공된 것이다.

% docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: devkuma
Password:
Login Succeeded

저장소에 이미지를 push한다

저장소에 push하는 이미지 이름은 “저장소 이름/이미지 이름"이라고 해야 한다. Docker Hub의 경우 저장소 이름은 계정 이름(필자의 경우 dekuma)이다.

앞에서 로컬에서 빌드한 이미지에는 저장소 이름이 명시되어 있지 않기 때문에 다음과 같은 docker tag 명령으로 Docker Hub에 push 할 별명을 설정해야 한다. 또한, 그러고 첫번째 인수에 별칭을 설정하고 싶은 “이미지 ID"를 넣고 두번째에 별칭을 지정한다. 각각 자신의 환경에 맞게 변경하면 된다.

% docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
myfirstapp   latest    ca9348c3dcd2   47 hours ago   67.7MB
% docker tag ca9348c3dcd2  devkuma/myfirstapp

docker images 이미지 목록을 표시하면 docker tag 결과 “devkuma/myfirstapp"가 추가 된 것을 확인 할수 있다. 여기서 “myfirstapp"과 “devkuma/myfirstapp"는 “IMAGE ID”(이미지 식별자)가 동일하기 때문에 모두 동일한 이미지임을 알 수 있다.

% docker images
REPOSITORY           TAG       IMAGE ID       CREATED        SIZE
devkuma/myfirstapp   latest    ca9348c3dcd2   47 hours ago   67.7MB
myfirstapp           latest    ca9348c3dcd2   47 hours ago   67.7MB

다음은 docker push 명령으로 저장소에 이미지를 push한다.

% docker push devkuma/myfirstapp
Using default tag: latest
The push refers to repository [docker.io/devkuma/myfirstapp]
59714c8e53ee: Pushed
8b0d10b320d2: Pushed
8fd4f6c343b1: Pushed
29f7edf0d8fd: Pushed
38f96c395e73: Pushed
c311a1e10929: Pushed
f566c57e6f2d: Mounted from library/alpine
latest: digest: sha256:5a06d6baf0481446a51c590099608145935d6f3e903aa2472c081fde0a12d6fe size: 1783

그럼 다시 브라우저에서 Docker Hub 대시 보드를 열고 push한 저장소 myfirstapp의 Tags(태그 목록)을 보면 태그 latest으로 이미지가 push 된 것을 확인 할수 있다. 이것은 조금 전에 push를 하여 이미지의 tag를 생략하여서 최신 이미지를 가리키는 기본 tag인 latest로 지정되었기 때문이다.

저장소에 push 된 이미지

이미지의 버전 관리 등의 목적으로 태그를 명시적으로 지정하려면 다음과 같이 이미지 이름으로 리포지토리 이름/이미지 이름:태그라고 태그를 명시적으로 넣어서 다시 push를 해보도로 하자.

% docker tag ca9348c3dcd2 devkuma/myfirstapp:0.0.1
% docker push devkuma/myfirstapp:0.0.1
The push refers to repository [docker.io/devkuma/myfirstapp]
59714c8e53ee: Layer already exists
8b0d10b320d2: Layer already exists
8fd4f6c343b1: Layer already exists
29f7edf0d8fd: Layer already exists
38f96c395e73: Layer already exists
c311a1e10929: Layer already exists
f566c57e6f2d: Layer already exists
0.0.1: digest: sha256:5a06d6baf0481446a51c590099608145935d6f3e903aa2472c081fde0a12d6fe size: 1783

다시 Docker Hub 대시 보드를 확인해 보면 TAG가 “0.0.1"인 이미지가 추가된 것을 확인 할 수 있을 것이다.

개인 저장소를 팀과 공유하려면?

지금까지는 개인의 공개 저장소에 이미지를 push하는 방법을 소개하였다. 공개 저장소이므로 다음 명령을 입력하면 누구나 이미지를 pull 받을 수 있게 된다.

% dokcer pull devkuma/myfirstapp

그다지 중요하지 않는 개인 프로젝트라면 개인 계정에 공개 저장소로 하여도 상관 없겠지만, 실제 개발은 팀의 개인 저장소를 제공하여 팀 구성원만 액세스 할 수 있게 해야 할 것이다.

Docker Hub는 비공개 저장소를 만들 수 있는데, 1개까지 무료고 그 이상은 유료이다. 요금은 Docker Hub 대시 보드에서 Pricing 페이지를 참조하도록 하자.

Docker Hub에는 다음 팀의 저장소를 만들기 위해 Organization와 Team 이라는 기능이 있다. Organization은 팀 멤버가 속한 조직을 의미하고, Team은 그 조직의 특정 역할을 가진 팀을 의미한다.

구체적인 예로서 문제를 방지하기 위해 이미지 관리자만 이미지를 push 할 수 있도록 하고, 다른 멤버는 pull만 할 수 있도록 하려면 다음과 같이 Organization 및 Team을 제공한다.

  • Organization으로 팀 구성원 모두를 등록한다. 이제 그 Organization 부하에 마련한 개인 저장소를 모든 구성원이 열람 할 수 있게 된다.
  • 이미지 관리자의 Team에 저장소에 대한 쓰기 권한을 부여하여, 그 Team에 이미지 관리자를 등록한다. 이제 이미지 관리자는 저장소에 이미지를 push를 할 수 있게 된다.
  • 이미지 이용자의 Team에 저장소에 대한 읽기 권한을 부여하여, 그 Team에 이미지 이용자로 등록한다. 이제 이미지 이용자는 저장소에 이미지를 pull를 할 수 있게 된다.

자세한 내용은 Docker 문서를 참조하도록 하자.

AWS ECR을 이용한 이미지 관리

다음 AWS에서 제공되는 이미지 저장소로 AWS ECR(EC2 Container Registry) 를 소개한다.

ECR이란?

ECR은 AWS에서 제공하는 이미지 관리용 클라우드 서비스이다. 다른 AWS 서비스와 쉽게 연동할 수 있기 때문에 AWS를 활용하고 있는 사람은 매우 사용하기 쉬운 서비스이다.

구체적으로는 다음과 같은 기능을 가지고 있다.

  • 완전 관리 형
    • AWS에서 관리 서비스로 관리되는 클라우드 서비스를 위해 직접 서버를 관리 할 필요는 없다.
  • Web UI
    • 브라우저를 사용하여 AWS 관리 콘솔에서 이미지 관리를 할 수 있다.
  • 다른 AWS 서비스와 쉽게 통합 할 수 있다.
  • 인증, 인가
    • IAM을 사용하여 이미지에 대한 인증 · 인가를 설정한다.
  • 팀에서 저장소 관리
    • 팀에서 공유 저장소를 만들 수 있다(IAM 기능을 사용하여 DockerHub의 Organization 및 Team에 해당되는 기능을 실현할 수 있다).

또한, ECR에 이용 요금은 없지만, 리포지토리에 저장하는 데이터 및 인터넷에 전송하는 데이터의 양에 따 부과된다. 자세한 내용은 요금표 를 확인하시기 바란다.

ECR에 이미지를 push/pull 해 보자

ECR을 사용하려면 다음을 사전에 준비해야 한다.

  • AWS 계정을 준비한다.
  • IAM 사용자를 생성한다.
    • 저장소에 대한 액세스는 IAM을 사용하여 인증 · 인가를 하기 위해 IAM 사용자가 필요하다. AWS 문서를 참고하여 IAM 사용자를 생성한다.
  • AWS CLI(커멘드 라인 인터페이스) 설치
    • 저장소 작업을 CLI로 수행하기 위해 AWS 문서를 참고하여 CLI를 사전에 설치한다.
    • aws configure 명령으로 키 및 지역의 설정도 하도록 한다.

주의: 이후에는 AdministratorAccess 정책이 부여된 IAM 사용자로 작업해야 한다.

레지스트리의 인증하기

이미지를 ECR에 push하려면 사전에 CLI에서 레지스트리에 대한 인증을 수행해야 한다. 인증은 Docker Hub와 동일하게 docker login 명령을 사용한다.

주의: ECR에 로그인 docker login 명령은 AWS 고유의 인증 정보를 부가 할 필요가 있고, AWS CLI 명령을 자동 생성하는 점에 주의한다.

다음 명령을 실행하여 docker login 명령을 받아온다. -region 후에는 저장소를 만들 영역을 지정한다. 로그인에 성공하면 docker login 명령이 표시된다. (참고: 아래는 인증 정보를 생략한다. 실제로 긴 문자열이 표시된다.)

$ aws ecr get-login --region us-west-2
docker login -u AWS -p xxx -e none
 https://xxx.dkr.ecr.us-west-2.amazonaws.com

다음 표시된 docker login 명령을 실행한다. 성공하면 “Login Succeeded"가 표시된다

$ docker login -u AWS -p xxx -e none
 https://xxx.dkr.ecr.us-west-2.amazonaws.com
Flag --email has been deprecated, will be removed in 1.14.
Login Succeeded

또한 AWS CLI에서 취득한 docker login 명령에는 유효 기간이 있다. 일정 시간이 서면 레지스트리에 액세스할 수 없게 되므로, 그 때는 레지스트리 다시 인증을 해야 한다.

리포지토리 만들기

이미지를 push한 후에는 대상으로 저장소를 제공한다.

브라우저에서 저장소를 만들려면 다음 단계를 수행한다.

  • https://console.aws.amazon.com/ecs/에 접속해서 AWS ECS(EC2 Container Service)의 관리 콘솔을 연다. (주의: ECR은 ECS에 통합되어 있어 이미지 관리도 ECS 관리 콘솔에서 수행한다.)
  • “저장소 설정 화면"에서 저장소 이름으로 “myfirstapp"를 입력하고 “다음 단계"를 클릭한다.
  • 저장소 URI가 표시되므로 이후의 작업에 대한 기록해 두길 바란다. URI의 형식은 계정 번호.dkr.ecr.지역 이름.amazonaws.com/저장소 이름이다.

또한 CLI에서 다음 명령을 만들 수 있다.

# aws ecr create-repository --repository-name myfirstapp
{
    "repository": {
        "registryId": "xxx",
        "repositoryName": "myfirstapp",
        "repositoryArn": "arn:aws:ecr:us-west-2:xxx:repository/myfirstapp2",
        "createdAt": 1490510283.0,
        "repositoryUri": "xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp2"
    }
}

저장소에 이미지를 push한다

저장소에 이미지를 push하려면 docker tag 명령으로 저장소 이름을 명시하는 이미지 이름의 별명을 준비해야 한다. 별칭은 관리 콘솔 또는 CLI의 응답에 표시된 저장소의 URI를 지정한다.

% docker tag myfirstapp xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp

docker push하면 이미지를 push 할수 있다.

% docker push xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp
The push refers to a repository [xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp]
17c42ed7fd27: Pushed
213ceaccd73e: Pushed
ac71ddba259e: Pushed
f8a68ba3c32d: Pushed
509e95f0d599: Pushed
3369321ad418: Pushed
23b9c7b43573: Pushed
latest: digest: sha256:7844dcb21756932f0cc93399519159f02f6c7b68f86af516d30c50b18b85d2ea size: 1783

이미지를 pull 할 때도 저장소를 명시하여 이미지 이름을 지정한다.

% docker pull xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp

개인 저장소를 팀과 공유하려면?

DockerHub와 동일하게 팀 구성원의 IAM 사용자 그룹에 대해 IAM 정책을 설정하여 이미지 관리자 모두에게 push를 허용하고 이미지 이용자 전원에게 pull을 허용 할 수 있다.

또한, ECR의 경우 기본적으로 저장소는 비공개이므로 허용한 상대에 대해 특정 작업을 허용해 나가는 방법을 해야 한다.

구체적인 권한 설정 방법은 다음 두 가지가 있다. 모두 궁극적으로는 IAM 정책이 IAM 사용자에게 적용된다는 점에서 동일하지만, 후자의 관리 콘솔을 사용하는 방법을 초보자도 알기 쉽기에 추천한다.

  • (ECR 이외의 서비스 공통) 직접 IAM 정책을 만들고 사용자에게 연결한다.
    • 저장소에 대한 적절한 사용 권한을 설정 한 IAM 정책을 만들고 허용 할 IAM 사용자 또는 사용자 그룹에 연결한다.
    • 자세한 내용은 AWS의 문서를 참조한다.
    • 장점
      • CLI에서 실행할 수 있기 때문에 자동 설정하고 싶은 경우에 유효하다.
    • 단점
      • IAM 자체가 복잡하기 때문에 IAM 정책을 쓰고 잘못 적절한 권한을 설정할 수없는 위험이있다. 실시시 확인이 필요하다.
  • ECR (한정) ECR 관리 콘솔에서 설정
    • 실시 방법
      • ECR 관리 콘솔에서 저장소의 “액세스 권한"페이지를 열고 저장소 관리 정책을 만들 수 있다.
      • 자세한 내용은 AWS의 문서 를 참조한다.
    • 장점
      • 관리 콘솔 GUI에서 작업 할 수있다. CUI에 익숙하지 않은 사람은 알기 쉽다.
      • 사용자를 선택하고 “pull 만」· 「push와 pull”· “모든 3 개의 ‘에서 허용 할 작업을 선택할 뿐이므로, 누구에게 무엇을 허용하고 있는지 알기 쉽다.
    • 단점
      • GUI 기반이므로 자동화 어렵다.

결론

여기서는 빌드한 이미지를 공유하는 방법으로 레지스트리 서비스를 소개하였다. 또한 구체적인 레지스트리 서비스로 Docker Hub와 Amazon ECR을 소재로 저장소를 관리하고 이미지를 push하는 방법에 대해 소개하였다. 이번에는 팀 내에서 공유 할 때 액세스 권한 관리 방법은 개요만 설명했지만, 실제 프로젝트에 적용 할 때 문제를 방지하기 위해서는 적절한 저장소의 권한 정책을 수립하는 것이 중요하다. 본문에서 소개한 Docker와 AWS의 문서를 참고하고 사전에 검증한 후에 도입하기를 추천한다.

4.5 - Docker 입문 | 4. Docker Compose를 사용하여 여러 컨테이너 배포

지금까지는 하나의 이미지 또는 컨테이너를 취급하는 방법을 진행해봤다. 그러나 실제 개발에서는 데이터베이스와 Web 서버 등의 여러 공정을 조합하여 시스템을 구성하는 것이 일반적이다. Docker를 사용한 시스템에서는 하나의 관심사를 하나의 컨테이너에 할당한다(Each container should have only one concern) 공식 문서에서도 권장되고 필연적으로 여러 컨테이너를 취급하는 경우가 종종 있다. 본 문서는 개발 및 테스트 환경을 위한 로컬 호스트에서 여러 컨테이너를 시작하는 방법으로 Docker Compose라는 도구를 소개한다.

여러 컨테이너 관리 도구 Docker Compose 개요

Docker Compose는 여러 컨테이너로 구성된 Docker 응용 프로그램의 설정을 작성하고 실행하기 위한 도구이다.

여러 컨테이너(데이터베이스, 캐시, Web API 등)로 구성된 시스템을 docker 명령만으로 시작하면 개별 컨테이너의 설정을 매개 변수로 지정하면서 컨테이너 의존 관계의 순서대로 명령을 실행해야 한다.

한편 Docker Compose를 사용하면 여러 컨테이너 설정과 의존 관계를 설정 파일에 작성하고 하나의 명령으로 여러 컨테이너를 한 번에 실행할 수 있다.

Docker Compose이 사용되는 주요 사례

개발 환경의 표준화

팀 구성원이 규칙대로 개발 환경을 수동으로 정비하면 시간이 걸릴뿐만 아니라 수작업 실수를 유발할 가능성이 있다. Docker Compose를 사용하여 설정 파일을 전달하면, 개발 환경의 세부 사항을 걱정하지 않고 하나의 명령으로 환경을 정비 할 수 있다. 이로 개발 환경 정비 작업을 간소화 할 수 있다.

테스트 환경의 자동화

CI(Continuous Integration)와 CD(Continuous Deployment)를 할 경우, end to end 테스트(모든 구성 요소를 결합하여 테스트)를 자동화하려면 이상적으로는 테스트마다 독립적인 테스트 환경을 제공 해야 한다. Docker Compose를 사용하면 필요한 테스트 환경을 명령어 1개로 시작할 수 있으며, 검사가 완료되면 쉽게 파기할 수도 있다.

단일 호스트 배포

운영 환경이 단일 서버의 경우 Docker Compose를 사용하여 배포 할 수 있다. 자세한 내용은 문서를 참조해라.

그러나 응용 프로그램을 확장하기 위해 다중 노드에 배포하려면 일반적으로 Docker Engine의 Swarm mode 라는 기능 또는 AWS ECSGoogle Container Engine과 같은 클라우드 클러스터 매니저가 더 적합하다.

단일 컨테이너를 시작으로 Docker Compose을 이해하기

Docker Compose 설정 파일(docker-compose.yml) 작성과 움직이는 방법을 알기 위해 Docker 이미지 빌드 페이지에서 만든 이미지를 사용하여 단일 컨테이너의 시작 및 중지하는 방법을 소개한다. 사전에 실습을 하지 않았다면 먼저 실습을 하고 오길 바란다.

docker-compose.yml 작성

다음은 앞에서 만든 이미지에서 컨테이너를 시작 위한 설정 파일이다. 위의 설정 파일을 docker-compose.yml라는 이름으로 저장한다.

version: '3'
services:
  myfirstapp:
    image: myfirstapp
    ports:
    - "8888:5000"

이 설정 파일에 내용은 아래와 같다.

  • Docker-Compose 파일 포맷 버전 “3” 이다.
    • 포맷에 대한 자세한 내용은 공식 문서를 참조해라.
    • (주의) Docker Compose 파일 포맷 버전 3은 Docker Engine 1.13.0 이상에서 동작 가능하다. 설치되어 있지 않은 경우에는 “[Docker 이미지 컨테이너 관리 메커니즘](Docker 이미지 컨테이너 관리 메커니즘)” 페이지 를 참고에 설치한다. 또한 Docker for Windows, Docker for Mac, Docker Toolbox를 설치하는 경우 Docker Compose도 자동으로 설치되기 때문에 추가 설치가 따로 필요 없다. Linux에 설치하는 방법에 대한 공식 문서를 참조해라.
  • 서비스 이름은 “myfirstapp” 이다.
    • services 아래에 나와 있는 항목은 외부에서 인식할 수 있는 기능 단위이며, “서비스"라고 한다.
    • 그러나 서비스는 컨테이너가 연결되기 때문에 서비스의 실태는 컨테이너이다.
  • 서비스에 연결하는 컨테이너는 “myfirstapp ‘라는 이미지에서 시작된다.
  • 컨테이너의 포트 5000 번을 호스트의 8888 번에 매핑한다. 이렇게 하면 컨테이너의 Web 서버에 https://localhost:8888 에 액세스 할 수 있게된다.

Docker Compose으로 컨테이너의 시작

docker-compose.yml에 있는 디렉토리에서 다음 명령을 실행하면 컨테이너가 시작된다.

# docker-compose up
.. 중간 생략 ...
Creating network "myfirstapp_default" with the default driver
Creating myfirstapp_1
Attaching to myfirstapp_1

Docker 이미지 빌드에서 보여준 바와 같이 https://localhost:8888/ 으로 접속하면 Web 응용 프로그램이 표시된다.

이는 다음 docker 명령을 실행하는 것과 같은 의미이다.

% docker run -p 8888:5000 myfirstapp

docker 명령과 비교하여 docker-compose 좋은 점은 설정을 대충 설정 파일에 기술하는 점에 있습니다. 주요 유스 케이스 절에서 소개 한대로, Docker Engine 및 Docker Compose을 설치하는 환경 만 있으면 docker-compose up에서 동일한 환경을 구축 할 수 있습니다.

Docker Compose가 지원하는 명령어

docker-compose updocker-compose.yml에 적힌 컨테이너의 작성 · 시작 등을 한꺼번에 처리 할 수 있다.

옵션을 붙이지 않고 실행하면 포 그라운드에서 실행되고 로그가 표준 출력에 표시된다. 다음과 같이 -d옵션을 붙이면 백그라운드에서 실행된다.

% docker -compose up - d

컨테이너를 중지하려면 다음 명령을 실행한다.

% docker -compose stop

컨테이너를 다시 시작하려면 다음 명령을 실행한다.

% docker -compose start

특정 컨테이너를 지정하여 시작할 수도 있다.

% docker -compose start myfirstapp

컨테이너의 정지 및 취소를 한꺼번에하려면 다음 명령을 실행한다.

% docker -compose down

기타 명령에 대한 자세한 내용은 공식 문서를 참조해라.

여러 컨테이너를 시작 해보자

Docker Compose의 사용법은 알게 되었다면, 좀 더 실용적인 예로 Docker 공식 샘플 voting app (투표 앱)을 소개한다.

이 어플리케이션은 5개의 서비스로 구성되어 있다.

voting app 구성

voting app의 구성 ( github.com/dockersamples/example-voting-app 에서 인용)

(주의) 여기에서는 Docker Compose 사용법이나 docker-compose.yml 작성법에 초점을 맞추고 설명하는 샘플의 개별 컨테이너의 구현 자세한 내용은 Github 저장소 를 참조해라.

서비스 이름 내용 보충
voting-app 사용자에게 투표를 촉구하는 Web 페이지를 표시하는 응용 프로그램. 데이터는 redis에 저장한다. Python과 Flask에 따르면 Web 응용 프로그램
redis 투표 결과를 임시로 저장 캐시. Redis
worker 투표 결과를 가져오고 Postgres 데이터베이스에 저장하는 작업자. .NET
db 투표 결과를 저장하는 데이터베이스. 데이터는 Docker volume 보관한다. Postgres
result-app 실시간 투표 결과를 표시하는 Web 응용 프로그램. Node.js에 따르면 Web 응용 프로그램

voting app 시작하기

응용 프로그램의 동작을 확인하기 위해 다음과 같이 Github 저장소에서 소스 코드를 받아와서 docker-compose up 명령 컨테이너를 시작한다. 처음에는 이미지 빌드가 달리는 시간이 걸리는 점에 주의하자.

% git clone https://github.com/dockersamples/example-voting-app.git
% cd example-voting-app
% docker-compose up

콘솔에 출력이 멈추고 컨테이너가 기동되면 브라우저에서 “https://localhost:5000"에 접속한다. 다음과 같은 투표 화면이 표시된다. CATS와 DOGS 중 하나를 선택한다.

투표 화면

브라우저에서 “https://localhost:5001"에 접속한다. 투표 결과 화면이 표시된다. 투표 화면에서 선택한 분에 투표가 들어있는 것을 확인할 수 있다.

투표 결과 화면

여러 컨테이너를 처리하는 docker-compose.yml 작성

여기에서 Docker Compose의 기능과 설정 파일 작성에 대해 설명하고 있다. 자세한 설정 파일의 작성 내용은 공식 문서를 참조해라.

voting-app의 설정 파일은 다음과 같다. 설정 파일에는 다음이 정의되어 있다.

  • 서비스(services)가 5 개(vote, result, worker, redis, db)
  • volume 1개 (db-data)
  • network가 2개 (front-tier, back-tier)
version: "3"

services:
  vote:
    build: ./vote
    command: python app.py
    volumes:
     - ./vote:/app
    ports:
      - "5000:80"
    networks:
      - front-tier
      - back-tier

  result:
    build: ./result
    command: nodemon --debug server.js
    volumes:
      - ./result:/app
    ports:
      - "5001:80"
      - "5858:5858"
    networks:
      - front-tier
      - back-tier

  worker:
    build:
      context: ./worker
    networks:
      - back-tier

  redis:
    image: redis:alpine
    container_name: redis
    ports: ["6379"]
    networks:
      - back-tier

  db:
    image: postgres:9.4
    container_name: db
    volumes:
      - "db-data:/var/lib/postgresql/data"
    networks:
      - back-tier

volumes:
  db-data:

networks:
  front-tier:
  back-tier:

services - 서비스 정의

단일 컨테이너의 예에서 설명한 것처럼 외부에서 인식할 수 있는 기능 단위를 “서비스"라고 한다. 서비스는 컨테이너가 연결되기 때문에 서비스의 실태는 컨테이너이다.

volumes - volume(데이터 지속성 영역)의 정의

volume 은 컨테이너의 라이프 사이클이 종료 된 후에도 데이터를 보관할 수 데이터 영역이다. 특징은 다음과 같다.

  • 데이터 지속성을 목적으로 한 기능을 위해 컨테이너가 삭제 되어도 volume이 명시 적으로 폐기되지 않는 한, volume에 있는 데이터는 유지된다.
  • volume은 특정 컨테이너 전용 volume뿐만 아니라 여러 컨테이너 사이에서 볼 수 volume도 만들 수 있다.
  • 호스트 측의 디렉토리를 volume으로 컨테이너에 탑재 할 수 있다.
    • 이 기능은 호스트와 컨테이너 사이에서 파일을 전달할 때 유효하다.

각 서비스의 volumes에는 서비스 별 volume 설정을 설명하고 있다. 예를 들어, vote 서비스는 호스트 측의 디렉토리 ./vote을 자동 컨테이너 전용 volume으로 컨테이너 디렉토리 /app에 마운트한다. 이렇게 하면 응용 프로그램 실행에 필요한 파일을 컨테이너로 받아 전달한다.

services:
  (생략)
  vote:
  (생략)
    volumes:
     - ./vote:/app

한편, db 서비스는 docker-compose.yml 최상위 volumes에 이름을 붙여 정의된 db-data라는 이름의 volume을 컨테이너의 디렉토리 /var/lib/postgresql/data에 마운트한다. db-data처럼 docker-compose.yml 최상위에 이름을 붙여 선언된 volume을 “네임드 volume(named volume)“라고 부른다.

services:
  (생략)
  db:
  (생략)
    volumes:
      - "db-data:/var/lib/postgresql/data"
volumes:
  db-data:
  • vote 서비스 volume와 같이, 서비스의 정의에 호스트 및 컨테이너 디렉토리 경로만 지정 volume 선언한 서비스 전용 volume 된다.
  • 한편 db-data 같은 네임드 volume은 여러 컨테이너에서 볼 수 있다.

networks - 네트워크 설정

network 는 서비스가 속한 네트워크이다.

voting-app에는 호스트 측에서 직접 데이터베이스에 액세스 의도하지 않은 데이터 변경되는 것을 방지하기 위해 데이터베이스 호스트에서 직접 액세스 할 수 없는 네트워크 back-tier에 배치하고, Web 서버는 호스트에서 액세스하는 네트워크 front- tier에 배치하고 있다.

이와 같이 각 서비스에 소속된 네트워크를 지정하기 위해서는 먼저 docker-compose.yml의 최상위에 네트워크를 선언한다.

networks:
  front-tier:
  back-tier:

그리고 각 서비스 정의 networks 서비스가 참여하는 네트워크를 지정한다. 다음의 경우 vote 서비스는 back-tierfront-tier에 속하고 redis 서비스는 back-tier에만 속하게 된다.

  vote:
  (생략)
    networks:
      - front-tier
      - back-tier
  (생략)

  redis:
  (생략)
    networks:
      - back-tier

동일한 네트워크에 속한 서비스 끼리는 호스트 이름으로 서비스 이름을 지정하여 상대 서비스에 연결할 수 있다. 예를 들어, vote 서비스와 redis 서비스는 모두 back-tier에 속하므로, vote 서비스에서 호스트 이름 redis에서 redis 서비스에 액세스 할 수 있다. 실제로 vote 서비스 구현(app.py)을 보면, 호스트 이름에 redis를 지정하고 있는 것을 알 수 있다 (포트는 생략되어 기본 포트 6379이 사용된다).

def get_redis():
    if not hasattr(g, 'redis'):
        g.redis = Redis(host="redis", db=0, socket_timeout=5)
    return g.redis

또한 Docker Compose는 처음 docker-compose up할시에 기본 네트워크를 하나 만들고 각 서비스를 기본 네트워크에 소속시킨다. 예를 들어, voting-app의 예라면 voting_default이 작성되어 있다.

$ docker-compose up
  (생략)
Creating network "voting_default" with the default driver

이 밖에 네트워크 설정에 대한 자세한 내용은 아래 공식 문서를 참조해라.

ports - 호스트, 컨테이너 사이의 포트 매핑

ports는 호스트, 컨테이너 사이의 포트 매핑을 지정한다. 컨테이너 포트 80번을 호스트의 포트 5000번에 매핑하여 브라우저에서 https://localhost:5000/ 으로 접속하면 vote 서비스 Web 응용 프로그램에 액세스 할 수 있다.

    ports:
      - "5000:80"

image - 사용하는 이미지의 지정

image에서 사용하는 이미지를 지정한다. 다음의 경우 redis 서비스는 기존의 이미지 redis:alpine을 사용하고 있는 것을 알 수 있다.

  redis:
    image: redis:alpine

build - 이미지 빌드

기존의 이미지에서 컨테이너의 요구 사항이 충족되지 않는 경우, build에서 이미지 빌드 설정을 지정한다. build를 지정하면 로컬 캐시에 이미지가 없는 경우 컨테이너 시작 전에 이미지 빌드가 달리고 이미지를 만들어 준다.

다음의 경우 vote 서비스는 ./vote 디렉토리에 빌드에 필요한 구성 파일이있는 것을 지정하고 있다.

services:
  vote:
    build: ./vote

실제로 example-voting-app/vote/를 열어 보면 Web 응용 프로그램에 필요한 여러 파일이 있고 그 안에 Docker 이미지를 구축하기 위한 Dockerfile 있다(Docker 이미지 빌드에 대해서는 “이미지 컨테이너 관리 메커니즘” 를 참조해라).

또한, image 및 build를 모두 지정하면 빌드 한 결과 이미지 이름은 image에서 지정한 이미지 이름이다.

command - 컨테이너 시작 명령

command는 컨테이너 시작 명령을 지정한다. vote 서비스는 Flask 는 Python 용 Web 프레임 워크로 구현되어 있다. 여기에서는 Web 어플리케이션의 진입 점인 app.py 을 실행하고 있다.

    command: python app.py

Docker Compose의 설명은 여기까지이다. 여기에서는 Docker Engine과 Docker Compose 기능의 일부만 다뤘다. 꼭 샘플 코드 및 공식 문서를 보고, 내용을 파악할 수 있으면 자신의 서비스에 활용 해보자.

결론

본 기사에서는 Docker 공식 견본인 voting-app 를 예로 들어 Docker Compose 설정 파일 작성 및 명령의 실행 방법에 대해 소개하였다.

미들웨어를 제공 할 때 이용자에게 Docker 이미지와 Docker Compose 설정 파일을 제공하면, 환경 세트를 쉽게 구축 할 수있는 점은 소프트웨어의 출처에 있어서도 이용자에게 매우 유용할 것이다.

다만 앞서 언급했듯이 Docker Compose는 단일 노드에 배포에 사용할 도구를 위한 스케일아웃을 할 수 없고, 프로덕션 환경에는 적합하지 않다. 다음은 프로덕션 환경에 적합한 클라우드 클러스터 매니저를 소개하도록 하겠다.

4.6 - Docker 입문 | 5. Docker Machine으로 Windows에 Docker 포스트 만들기

이번에는 Docker Machine이라는 도구를 사용하여 Windows PC에 Docker 호스트를 만드는 방법을 소개한다. Docker 호스트란 Docker가 설치되어 사용할 수 있는 상태가 되어있는 환경이다. Docker 호스트를 만드는 방법에 대해서는 예전에 “Docker 이미지 컨테이너 관리 메커니즘“에서 Docker for Windows와 Docker Toolbox라는 GUI 툴을 소개했는데, 이번에는 다루려고 하는 Docker Machine은 CLI 도구이다. Docker Machine은 VirtualBox 등의 가상 환경 도구가 있으면, 단 한줄의 명령의 실행으로 Docker 호스트를 만들어 준다.

Docker 호스트를 만들 수 없다!

Docker Machine을 다루기 전에 먼저 Docker Machine이 등장한 경위를 대해 알아 보자.

Docker의 특징의 하나로서, 응용 프로그램의 이식성을 높여 준다는 것을 잘들 수 있다. 예전에 “Docker 이미지 컨테이너 관리 메커니즘“에서도 Docker의 특징은 응용 프로그램을 “다양한 환경에 배포할 수 있다"있다는 내용과, “한 번 응용 프로그램을 Docker 컨테이너의 이미지로 만들면 그대로 다양한 플랫폼에서 실행된다"고 설명하였다.

이런 이식성의 특징은 당연히 Docker를 이용할 수 있는 환경 즉, Docker 호스트 없이는 성립되지 않는다. Docker 호스트가 있어야 비로소 응용 프로그램에 높은 이식성을 가져올 수 있다.

그러나 Docker 호스트를 생성하는 것은 결코 쉬운 일이 아니다. 특히 Docker가 등장한 2013 년은 그랬다. 예를 들어, Docker 호스트를 생성하기 위해서는 OS가 있어야 하는데, 도대체 어떤 OS를 준비해야 좋을까? 사실 Docker가 등장한 초기에 지원된 OS는 Ubuntu 12.04/12.10 만 이었다. 그 버전의 Ubuntu 환경을 아니면 새로 만들거나 기존의 Ubuntu 아닌 Linux에서는 패치 등의 작업이 필요했던 것이다.

2013년 11월 출시한 Docker 0.7부터 모든 주요 Linux 배포판이 지원되었지만 Docker 호스트를 만들 수 있는 기술은 아직 그다지 발전하지 않았다고 말할 수 있다.

Boot2Docker의 등장

그러던 중 2013년 12월에 개최 된 Docker 회사의 이벤트에서 Boot2Docker가 발표되었다.

Boot2Docker는 가상 환경 도구인 VirtualBox에 Docker 호스트를 만드는 도구이다. 초기에는 Mac에서만 지원되고 있었지만, 후에 Windows도 지원되게 되었다.

Boot2Docker의 구성은 다음의 두 가지로 나눌 수 있다.

  1. Docker 호스트를 만드는 기반이 되는 OS 이미지 파일
  2. Docker 호스트를 작성 · 관리하는 위한 CLI 도구

Boot2Docker 개요

OS 이미지 파일은 Tiny Core Linux라는 가벼운 Linux를 기반으로 하고 있다. Ubuntu 등 다목적 서버용 OS와 달리 Docker 호스트에 필요한 최소한의 것들만 포함되어 있기 때문에, 크기는 수십 MB로 매우 가볍다.

CLI 도구 명령 이름은 init, up, down등 직관적으로 알기 쉽고, Linux에 대한 지식을 그다지 필요로 하지 않는다.

이러한 OS와 도구를 세트로 제공 해주는 덕분에 Docker 또는 Linux에 그다지 친숙하지 않은 사용자도 쉽게 확실하게 가벼운 Docker 호스트를 만들 수 있다는 것이다.

Docker Machine의 등장

Boot2Docker의 등장으로 Docker 호스트의 생성은 매우 간단 해졌다. 이 Boot2Docker의 후속으로 개발된 것이 Docker Machine이다. Docker Machine은 2014년 12월 DockerCon EU 에서 발표되었다.

Docker Machine은 Boot2Docker와 마찬가지로 간편하고 가벼운 Docker 호스트를 생성하고 관리 할 수있는 도구이다. 기술적으로도 다음과 같이 Boot2Docker의 성과를 계승 발전시킨 것으로 되어 있다.

  1. Docker 호스트를 만드는 기반이 되는 OS 이미지 파일은 Boot2Docker 등의 이미지를 사용할 수 있다.
  2. Docker 호스트를 작성 · 관리하기위한 CLI 도구에서는 Boot2Docker에서 마이그레이션 되었다.
  3. 가상 환경으로는 VirtualBox뿐만 아니라 Hyper-V와 AWS 등 다양한 것들을 이용 가능하다.

Docker Machine 개요

이 중 Boot2Docker과 가장 크게 다른 점은 3번 가상 환경이다. Docker Machine은 드라이버라는 구조를 가지고 있으며, VirtualBox 드라이버와 AWS 드라이버 등 드라이버를 구분하여 다양한 가상 환경에 Docker 호스트를 작성할 수 있게 되었다. 현재는 10여가지 종류의 드라이버가 미리 Docker Machine에 내장되어 있다. 또한 드라이버는 직접 만드는 것도 가능하며, 20개 이상의 타사 드라이버가 존재한다.

Docker Machine 덕분에 Docker 호스트의 생성은 더욱 쉬워졌습니다. 이 후에도 Docker 호스트를 만들기위한 새로운 도구가 개발되어갑니다 만, 그것에 대해 마지막 정리로 설명합니다.

사전 준비

그럼, 여기에서 Docker Machine의 구체적인 사용법에 대해 소개하겠다. 개요는 다음과 같다.

  • 사전 준비
  • Docker Machine 설치
  • Docker 호스트 만들기
  • Docker 호스트에 로그인
  • Docker 호스트에서 Hello World

우선 사전 준비로 Windows 10에 VirtualBox 를 설치한다. 그러고 당연히 되겠지만 PowerShell 명령을 실행할 수 있는지 확인한다.

여기서 필자가 이용한 환경은 다음과 같다.

  • Windows 10 Pro
  • VirtualBox 6.1.22
  • PowerShell 5.1.19041.1023

각각 간단하게 설명하겠다.

Windows 10

Docker 호스트를 만드는 최신 도구로 “Docker for Windows"라는 도구는 Windows 10 이상에서 동장하지만, Docker Machine은 Windows 7 이상부터 동작한다. 혹시 Windows 7 이하 버전을 사용하는 사람이 있다면 참고 바란다.

VirtualBox

VirtualBox는 Docker Machine의 기본 가상 환경 도구이다. Windows 용 설치 프로그램은 여기에서 다운로드 할 수 있다. 앞에서 설명하였듯이 Docker Machine은 AWS 등도 사용할 수 있지만, 우선 Boot2Docker에 있어서, 문제 해결 정보도 풍부한 VirtualBox를 사용하는 것을 추천한다.

참고로 Windows에 Hyper-V를 사용하고 싶은 경우는 Hyper-V와 VirtualBox를 동시에 사용하는 것은 기술적으로 불가능하므로 주의하시기 바란다.

PowerShell

Windows의 CLI로써, 명령 프롬프트를 떠올리는 사람이 많다고 생각되지만, 여기서는 PowerShell을 사용한다.

PowerShell은 Windows에 처음부터 설치되어 있지만 Windows 7의 경우 이전 버전 가능성이 높다. PowerShell 버전은 PowerShell에서 다음과 같이 입력하면 표시된다.

PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.1023

(이하 생략)

$PSVersionTable 버전 정보가 저장되는 변수로써 PowerShell이 자동으로 생성된다.

Docker Machine 설치

이것으로 사전 준비가 완료되면 Docker Machine을 설치해 보자. 설치는 간단하다. 바이너리 파일을 다운로드하여 Path를 설정하기만 하면 된다.

이번 이용하는 Docker Machine 버전은 v0.16.2이다. 바이너리 파일은 Docker Machine의 GitHub의 페이지 에서 다운로드할 수 있다. Windows 64 비트 버전의 파일 이름은 “docker-machine-Windows-x86_64.exe” 이다. 다운로드한 파일 이름을 “docker-machine.exe"으로 변경하고 적당한 장소에 저장하도록 한다. 여기에서는 아래와 같이 다음 위치에 파일이 있다는 전제로 설명하겠다.

C:\docker\docker-machine.exe

동작 확인을 위해 PowerShell을 열고 다음 명령을 실행하자.

PS C:\> C:\docker\docker-machine.exe version
docker-machine.exe version 0.16.2, build bd45ab13

버전 정보가 출력된다.

매번 이렇게 긴 경로와 함께 명령어를 입력할 수 불편하니, 윈도우 환경 변수 Path에 C:\docker를 추가하도록 하자(환경 변수에 추가하는 방법은 검색해 보면 흔하게 찾을 수 있을 것이다). 그러고 PowerShell을 다시 시작하고 다음 명령을 실행한다.

PS C:\> docker-machine version
docker-machine.exe version 0.16.2, build bd45ab13
PS C:\>

정보가 출력되면 성공이다. 아까와 달리 docker-machine끝에 .exe 붙이지 않았다. .exe이 있어도 동작하지만 이렇게 생략해도 된다.

이제 설치가 완료되었다. 드디어 실제로 Docker Machine을 동작시켜 Docker 호스트를 만들어 보자.

Docker 호스트 만들기

Docker Machine은 다음 단 한줄의 명령을 실행하면 Docker 호스트를 만들어줍니다.

PS > docker-machine create --driver virtualbox devkumahost

주의 : 기존에 이미 Hyper-V가 설치되어 있다면 docker-machine create 명령어를 실행하면 아래와 같이 명령어 발생할 것이다.

PS C:\> docker-machine create --driver virtualbox devkumahost
Creating CA: C:\Users\kimkc\.docker\machine\certs\ca.pem
Creating client certificate: C:\Users\kimkc\.docker\machine\certs\cert.pem
Running pre-create checks...
Error with pre-create check: "This computer is running Hyper-V. VirtualBox won't boot a 64bits VM when Hyper-V is activated. Either use Hyper-V as a driver, or disable the Hyper-V hypervisor. (To skip this check, use --virtualbox-no-vtx-check)"

위에서 언급 했듯이 Hyper-V와 VirtualBox를 동시에 사용하는 것은 기술적으로 불가능하므로, 둘 중에 하나를 사용하지 말아야 한다. 여기 예에서는 VirtualBox를 사용할 것이기에 Hyper-V 기능을 끄기로 하겠다. 끄는 방법은 [제어판>프로그램]에 가서 “Windows 기능 켜기/끄기"에서 Hyper-V 관련 옵션을 빼고 재부팅하면 된다.

create는 Docker 호스트를 작성하는 명령으로 devkumahost는 Docker 호스트의 이름이다. --driver(또는 -d) 드라이버를 지정하는 옵션으로, 여기에서 VirtualBox 드라이버가 지정되어 있다. VirtualBox 드라이버는 기본 드라이버이므로 다음과 같이 --driver는 생략 할 수도 있다.

PS > docker-machine create devkumahost

실행하면 다음과 같은 로그가 출력된다.

PS C:\> docker-machine create --driver virtualbox devkumahost
Running pre-create checks...
(devkumahost) Image cache directory does not exist, creating it at C:\Users\kimkc\.docker\machine\cache...
(devkumahost) No default Boot2Docker ISO found locally, downloading the latest release...
(devkumahost) Latest release for github.com/boot2docker/boot2docker is v19.03.12
(devkumahost) Downloading C:\Users\kimkc\.docker\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v19.03.12/boot2docker.iso...
(devkumahost) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100%
Creating machine...
(devkumahost) Copying C:\Users\kimkc\.docker\machine\cache\boot2docker.iso to C:\Users\kimkc\.docker\machine\machines\devkumahost\boot2docker.iso...
(devkumahost) Creating VirtualBox VM...
(devkumahost) Creating SSH key...
(devkumahost) Starting the VM...
(devkumahost) Check network to re-create if needed...
(devkumahost) Windows might ask for the permission to create a network adapter. Sometimes, such confirmation window is minimized in the taskbar.
(devkumahost) Found a new host-only adapter: "VirtualBox Host-Only Ethernet Adapter #2"
(devkumahost) Windows might ask for the permission to configure a network adapter. Sometimes, such confirmation window is minimized in the taskbar.
(devkumahost) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(devkumahost) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: C:\docker\docker-machine.exe env devkumahost

Boot2Docker 이미지 파일 (boot2docker.iso)을 다운로드하고 있는 것을 확인 할 수 있다. 다운로드한 파일이 저장되어 다음 Docker 호스트를 만들 때 재사용된다.

(devkumahost) Copying C:\Users\kimkc\.docker\machine\cache\boot2docker.iso to C:\Users\kimkc\.docker\machine\machines\devkumahost\boot2docker.iso...
(devkumahost) Creating VirtualBox VM...

이 로그는 다운로드한 Boot2Docker 이미지 파일을 바탕으로 VirtualBox의 가상 머신을 생성하고 있음을 보여준다.

(devkumahost) Creating SSH key...

Docker 호스트에 SSH 연결하는데 필요한 키 쌍을 생성한다. 이 외에도 공개 키를 Docker 호스트의 가상 디스크에 포함 등 SSH 연결에 필요한 설정이 자동으로 이루어진다.

Docker is up and running!

Docker 호스트에서 Docker이 동작하고 있다!

여기까지 create명령을 한 줄만 실행했을 뿐있었다. 시간은 필자의 환경에서는 몇 분밖에 안걸렸다.

정말 Docker 호스트가 만든 여부 확인해 보도록 하자.

PS C:\> docker-machine ls
NAME          ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER      ERRORS
devkumahost   -        virtualbox   Running   tcp://192.168.99.100:2376           v19.03.12

ls명령은 Docker 호스트의 목록을 출력하는 명령이다. “devkumahost” 라는 Docker 호스트가 작성되어 있는 것이 확인 된다. 상태는 “Running"이므로 실행중인 것이다. “v19.03.12"는 이용중인 Docker 버전이다.

Docker 호스트에 로그인

다음은 만든 Docker 호스트에 로그인하여 보자.

로그인은 SSH으로 한다. 이미 SSH에 대한 설정은 자동으로 완료되었기에 다음과 같이 Docker Machine의 ssh 명령에 호스트 이름을 지정하면 로그인 할 수 있다.

PS C:\> docker-machine ssh devkumahost
   ( '>')
  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
 (/-_--_-\)           www.tinycorelinux.net

docker@devkumahost:~$

이 처럼 Docker Machine을 사용하여 Docker 호스트를 작성하면, SSH에 대해서는 거의 신경쓸 필요는 없다.

Docker 호스트에 Hello World

Docker 호스트에 로그인 할 수 있었고, 다음은 Docker의 동작 확인해 보자.

Docker는 이미 Docker 호스트에 설치되어 즉시 동작하는 상태이다. Docker 호스트에 로그인 한 상태에서 다음과 같이 hello-world 컨테이너를 생성하고 시작하자.

docker@devkumahost:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

docker@devkumahost:~$

앞중간에 부분에 “Hello from Docker!” 라고 표시가 되었다!

이것으로 create 명령으로 Docker 호스트를 만들고, ssh로 로그인하여 Docker를 사용할 수 있게 되었다.

사실 ssh명령에 로그인하지 않아도 Windows Docker CLI가 있으면 Docker를 사용할 수 있지만, 그 방법은 이후의 다시 소개하도록 하겠다.

다음은 기타 Docker Machine 명령이나 문제가 있을 때 해결 방법을 몇 가지 소개해 보겠다.

Docker 호스트의 기동 · 정지

여기까지 작업을 진행해 왔다면 Docker 호스트 “devkumahost"에 로그인 한 상태라고 생각된다.

우선은 Linux의 exit명령을 실행하여 Docker 호스트에서 로그 아웃한다.

docker@devkumahost:~$ exit
logout
PS C:\>

로그 아웃해도 Docker 호스트 기동되고 있다. status명령으로 상태를 확인하자.

PS C:\> docker-machine status devkumahost
Running

“Running"이므로, 역시 기동되어 있다.

그럼 stop 명령으로 중지해 보자.

PS C:\> docker-machine stop devkumahost
Stopping "devkumahost"...
Machine "devkumahost" was stopped.

정지되었다. status 명령로 다시 확인 하면 “Stopped"이라고 표시된 것을 확인 할수 있다.

PS C:\> docker-machine status devkumahost
Stopped

이어 start명령으로 다시 시작해 보자.

PS C:\> docker-machine start devkumahost
Starting "devkumahost"...
(devkumahost) Check network to re-create if needed...
(devkumahost) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(devkumahost) Waiting for an IP...
Machine "devkumahost" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

시작되었다. status 명령로 다시 확인 하면 “Running"이라고 표시된 것을 확인 할수 있다.

PS C:\> docker-machine status devkumahost
Running

stop, start명령 대신 restart명령을 실행하면 중지한 후 다시 시작한다.

PS C:\> docker-machine restart devkumahost
Restarting "devkumahost"...
(devkumahost) Check network to re-create if needed...
(devkumahost) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(devkumahost) Waiting for an IP...
Waiting for SSH to be available...
Detecting the provisioner...
Restarted machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

Docker 호스트 제거

필요 없게된 Docker 호스트는 rm 명령으로 삭제할 수 있다.

PS C:\> docker-machine rm devkumahost
About to remove devkumahost
WARNING: This action will delete both local reference and remote instance.
Are you sure? (y/n): y
Successfully removed devkumahost

삭제되었는지 확인하려면 ls명령으로 Docker 호스트의 목록을 확인해 보면 된다.

PS C:\> docker-machine ls
NAME   ACTIVE   DRIVER   STATE   URL   SWARM   DOCKER   ERRORS

또는, VirtualBox의 GUI에서 확인해도 된다. 삭제된 Docker 호스트는 표시되지 않을 것이다.

Docker 호스트의 설정 정보

inspect 명령을 실행하면 Docker 호스트의 설정 정보를 JSON 형식으로 출력 할 수 있다.

PS C:\> docker-machine inspect devkumahost
{
    "ConfigVersion": 3,
    "Driver": {
        "IPAddress": "192.168.99.102",
        "MachineName": "devkumahost",
        "SSHUser": "docker",
        "SSHPort": 2644,
        (이하 생략)         

또한, 다음 폴더에 설정 파일이 저장되어 있으며, 텍스트 편집기 등으로 열어서 볼 수 있습니다.

<사용자 홈 디렉토리>\ .docker\machine\ machines\< 호스트 이름>\ config.json

Boot2Docker 버전을 지정

Docker Machine은 특히 아무것도 지정하지 않으면 최신 Boot2Docker 이미지 파일을 다운로드하여 사용할 수 있게 된다.

특정 버전의 Boot2Docker을 이용하고 싶은 경우에는 --virtualbox-boot2docker-url에 이미지 파일의 URL을 지정한다.

PS C:\> docker-machine create --virtualbox-boot2docker-url https://github.com/boot2docker/boot2docker/releases/download/v19.03.12-ce/boot2docker.isl devkumahost1903
Running pre-create checks...
(devkumahost1903) Boot2Docker URL was explicitly set to "https://github.com/boot2docker/boot2docker/releases/download/v19.03.12-ce/boot2docker.isl" at create time, so Docker Machine cannot upgrade this machine to the latest version.
Creating machine...
(devkumahost1903) Boot2Docker URL was explicitly set to "https://github.com/boot2docker/boot2docker/releases/download/v19.03.12-ce/boot2docker.isl" at create time, so Docker Machine cannot upgrade this machine to the latest version.
(devkumahost1903) Downloading C:\Users\kimkc\.docker\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v19.03.12-ce/boot2docker.isl...
(devkumahost1903)
(devkumahost1903) Creating VirtualBox VM...
(devkumahost1903) Creating SSH key...
Error creating machine: Error in driver during machine creation: C:\Program Files\Oracle\VirtualBox\VBoxManage.exe storageattach devkumahost1903 --storagectl SATA --port 0 --device 0 --type dvddrive --medium C:\Users\kimkc\.docker\machine\machines\devkumahost1903\boot2docker.iso failed:
VBoxManage.exe: error: Could not get the storage format of the medium 'C:\Users\kimkc\.docker\machine\machines\devkumahost1903\boot2docker.iso' (VERR_NOT_SUPPORTED)
VBoxManage.exe: error: Details: code VBOX_E_IPRT_ERROR (0x80bb0005), component MediumWrap, interface IMedium, callee IUnknown
VBoxManage.exe: error: Context: "OpenMedium(Bstr(pszFilenameOrUuid).raw(), enmDevType, enmAccessMode, fForceNewUuidOnOpen, pMedium.asOutParam())" at line 191 of file VBoxManageDisk.cpp
VBoxManage.exe: error: Invalid UUID or filename "C:\Users\kimkc\.docker\machine\machines\devkumahost1903\boot2docker.iso"

여기서 에러가 나는데… 나주엥 찾아보겠다.ㅜㅜ

Docker 호스트 명령의 실행

ssh명령은 인수 Docker 호스트 명령을 사용하여 수행 할 수 있습니다. 별도 로그인 로그 아웃 명령을 입력 할 필요가 없습니다. OpenSSH 등의 SSH 클라이언트에도 같은 기능이 있군요.

다음 예제에서는 “devkumahost"에 ls 명령을 실행하여 /home디렉토리의 내용을 표시하고 있다.

PS C:\> docker-machine ssh devkumahost ls /home
docker
dockremap
PS C:\>

Docker 호스트에 프록시 정보를 설정

방금 전의 hello-world를 실행하면 다음과 같은 오류가 나타날 수 있다.

docker@devkumahost:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on 10.0.2.3:53: no such host.
See 'docker run --help'.

원인의 하나로서, 회사나 학교의 HTTP 프록시를 통과할 수 없어서 일 수 있다. 이런 경우 Docker 호스트에 프록시 정보를 설정한다.

프록시 정보는 create명령의 옵션으로 설정할 수 있습니다.

PS> $http_proxy = 'https://myproxy.com:1234'
PS> $https_proxy = 'https://myproxy.com:1234'
PS> docker-machine create --engine-env HTTP_PROXY=$http_proxy --engine-env HTTPS_PROXY=$https_proxy myhost

$http_proxy$https_proxy은 PowerShell 변수이다. --engine-env는 Docker가 참조하는 환경 변수를 지정하는 옵션으로 “변수이름=값” 형식으로 설정한다.

사용자 이름과 암호가 필요한 경우는 다음과 같이 설정한다.

PS> $http_proxy = 'https://user:password@myproxy.com:1234'
PS> $https_proxy = 'https://user:password@myproxy.com:1234'
PS> docker-machine create --engine-env HTTP_PROXY=$http_proxy --engine-env HTTPS_PROXY=$https_proxy myhost

이 사용자 이름과 암호는 방금 전의 inspect명령을 사용하면 일반 텍스트로 보이므로 있으므로 주의가 필요하다. 또한 Docker Machine 설정 파일(config.json)에 일반 텍스트로 저장된다. GitHub에 개선 요구가 높아지고 있지만 아직까지 지원되지 않는다.

기본 호스트 이름 “default”

Docker 호스트의 이름은 “default"라는 이름에 설정해 두면 편리하다. 일부 명령은 호스트 이름을 생략 할 수 있기 때문이다.

예를 들어, docker-machine start라는 식으로 호스트 이름을 지정하지 않고 start명령을 실행하면 “default"라는 Docker 호스트를 시작하게 된다. 마찬가지로 docker-machine stop는 “default"라는 Docker 호스트를 중지하게 된다.

도움말

이상 소개 한 이외에도 Docker Machine은 다양한 명령과 옵션을 제공한다. 다음 명령으로 도움말이 표시되기에 여러가지 연습해 보면 좋을 것이다.

PS C:\> docker-machine
Usage: docker-machine.exe [OPTIONS] COMMAND [arg...]

(중간 생략)

Commands:
  active                Print which machine is active
  config                Print the connection config for machine
  create                Create a machine
  env                   Display the commands to set up the environment for the Docker client
  inspect               Inspect information about a machine
  ip                    Get the IP address of a machine

(이하 생략)
PS C:\> docker-machine create
Usage: docker-machine create [OPTIONS] [arg...]

(중간 생략)

Options:

   --driver, -d "virtualbox"                                                                            Driver to create machine with. [$MACHINE_DRIVER]
   --engine-env [--engine-env option --engine-env option]                                               Specify environment variables to set in the engine
   --engine-insecure-registry [--engine-insecure-registry option --engine-insecure-registry option]     Specify insecure registries to allow with the created engine
 (이하 생략)

결론 : Docker Machine과 관련 도구

본 기사에서는 Docker Machine을 사용하여 Windows에 Docker 호스트를 만드는 방법을 소개하였다.

Docker Machine 이외에도 Docker 회사에서는 다양한 도구를 개발하고 있다. 다음 조금 긴하지만, 그 도구 중 Docker Machine은 도대체 어떤 자리 매김에 있는지 보면서, 정리해 보도록 하겠다.

다음은 Docker Machine 관련 도구와 출판 년도(괄호)를 보여준다.

  • Boot2Docker (2013)
  • Docker Compose (Fig) (2014)
  • Kitematic (2014)
  • Docker Machine (2014)
  • Docker Toolbox (2015)
  • Docker for Windows (2016)
  • InfraKit (2016)
  • LinuxKit (2017)

Docker가 발표된 것은 2013년 3월이다. 얼마 지나지 않아, Docker사 밖에서 다양한 도구가 개발되어 갔다. Docker사는 그러한 도구를 적극적으로 자사에 가져왔다.

Docker Compose를 사용하여 여러 컨테이너 배포“에서 소개한 Docker Compose는 원래 Fig라는 이름으로 영국의 시작이 개발한 도구였지만, 곧 Docker 사에 인수되었다 .

Kitematic는 GUI에서 Docker를 조작하는 도구이다. 2015년에 이것도 Docker 사에 인수되었다.

그러던 중 2014년 12월 DockerCon EU에서 Docker Machine이 발표되었다. 이미 설명했듯이 Docker Machine은 Boot2Docker의 성과를 발전시킨 도구이다.

Docker Toolbox는 Windows와 Mac에서도 Docker를 쉽게 사용할 수 있도록 하자는 도구이다. 내용은 Docker Compose, Kitematic, Docker Machine 등을 한 패키지로 한 것이다. 말하자면 Docker 사가 해왔던 개발 도구의 집대성이라고도 말할 수 있는 도구였던 셈이다.

여기에서 사람 구분이 새로운 흐름이 시작된 것 같은 느낌을받습니다.

다음 Docker for Windows는 Toolbox와 마찬가지로 Windows에서도 Docker를 쉽게 사용할 수 있도록 하자는 도구이다. 그러나 Docker for Windows는 Docker 호스트를 작성하는 방법으로 기본적으로 Docker Machine을 사용하지 않는다. Docker Machine은 클러스터 환경을 만드는 경우 등 필요한 경우 사용 도구는 평가한다. 가상 환경 도구도 VirtualBox 대신 Hyper-V를 채용하고 있다.

InfraKit과 LinuxKit는 Docker 호스트의 작성 · 관리 및 이미지 파일을 만들 도구이다. Docker Machine보다 강력하고, Boot2Docker보다 유연하게 커스터마이즈할 수 있는 도구라고 해도 좋을 것이다. 이는 단적으로 나타내고 있는 것이 다음 Docker Machine의 GitHub 저장소의 코멘트이다. 모두 Docker 사의 개발자의 코멘트이다.

댓글 1 :

We have introduced more focused projects such as infrakit for multi host production deployments, linuxkit for a maintainable and extensible replacement for boot2docker

댓글 2 :

On the other hand, while we still want to maintain the project and make sure the people using it today can continue to do so as long as it is useful, we will not be adding any new feature to the project from here onward

즉, Docker사로는 향후 InfraKit과 LinuxKit에 주력해 나갈, Docker Machine은 계속 유지하고 가지만 새로운 기능은 추가하지 않는다는 것이다. 이 정책은 아직 공식적으로 발표 된 것은 없다. 또한 Docker Machine은 오픈 소스 소프트웨어이기 때문에 유지가 포크하고 기능을 추가하는 것을 계속할지도 모른다. 그러나 Docker Machine이 지금 큰 기로에 서있는 것은 틀림 없을 것이다.

지금까지 필자 개인적으로는 Docker에 아직 익숙하지 않은 분은 먼저 Docker Machine을 이용하는 것이 좋다고 생각한다. Docker for Windows와 같은 GUI 도구는 좋든 나쁘든 내부 구조가 보이지 어려운 도구이다. Docker Machine을 사용한 경험이 있으면 Docker for Windows가 대략 무엇을 해주는 도구인지 이해하기 쉽고, Docker를 잘 다룰 수있게되는 것도 빠른 것이다.

본 기사에서 소개 한대로 Docker Machine은 간편하게 사용할 수있는 도구이다. Docker을 효율적으로 이해하고 다룰 수있게 되기 위해서도 Docker Machine을 만져 보면 좋을 것이다.

4.7 - Docker 입문 | 6. Docker Engine의 구조를 체험하자

이번에는 Docker Engine의 구조에 대해 클라이언트 서버 모델의 관점에서 설명하겠다. Docker Engine API를 호출하거나 원격으로 연결하는 등, Docker Engine의 구조를 체험적으로 이해하고 가자.

Docker Engine 개요

Docker Engine은 Docker의 핵심 소프트웨어이다. 지금까지 종종 등장했던 docker rundocker build 등의 명령과 그 명령에 의해 실행되는 이미지 빌드, 컨테이너 실행하는 등의 다양한 작업을 할 것을 정리하여 Docker Engine이라고 한다.

단순히 Docker라고 하면 이 Docker Engine을 가리키는 경우도 있고, Docker Hub와 같은 주변 서비스 및 도구를 포함한 Docker Platform을 가리키는 경우도 있다. Docker Platform처럼 넓은 의미에서 Docker과 구별 할 때 Docker Engine이라는 말은 사용된다.

공식 문서에 따르면, Docker Engine은 주로 다음의 3가지 요소로 구성되어 있다.

  1. Docker CLI
  2. Docker Engine API
  3. Docker 데몬

Docker CLIdocker rundocker build 등의 Docker 명령을 실행하는 커멘드 라인 도구이다. Docker CLI는 입력된 Docker 명령에 따라 Docker Engine API를 호출한다. Docker 데몬은 Linux 데몬 프로세스에서 Docker Engine API가 호출되는 것을 기다리고 있다가, 호출된 Docker Engine API에 따라 이미지의 빌드 및 컨테이너의 시작 등을 실행한다.

이처럼 Docker Engine은 클라이언트 서버 모델의 응용 프로그램이라 할 수 있다. 클라이언트인 Docker CLI가 Docker Engine API를 통해 서버인 Docker 데몬에 처리를 요청하고 응답을 받는다.

Docker Engine 개요

Unix 소켓 통신과 TLS 통신

위의 그림과 같이 Docker CLI가 Docker 호스트에 있는지 외부에 있는지에 따라 Docker 데몬과 통신 방식은 다르다.

Docker CLI가 Docker 호스트에 있는 경우는 Unix 도메인 소켓(이하, Unix 소켓)을 이용하여 Docker 데몬과 통한다. Unix 소켓은 동일한 시스템에 있는 프로세스끼리 통신을 할 수 있는 구조이다. 마지막은 docker-machine ssh명령을 사용하여 Docker 호스트에 로그인 한 후 Docker 호스트에 있는 Docker CLI 명령을 실행하고 있었으므로, Unix 소켓 통신을 하고 있었던 거다.

Docker CLI가 Docker 호스트의 외부에 있는 경우 TCP 소켓을 사용하여 Docker 데몬과 통신한다. TCP 소켓의 경우 HTTP를 그대로 이용하는 것이 아니라, 어떠한 보안 대책을 실시하는 것이 추천되고 있다. 그 중 하나가 TLS 이다. Docker Engine은 TLS를 사용하여 HTTP를 암호화 된 HTTPS 통신을 실시하는 것과 동시에 클라이언트와 서버를 신뢰할 수있는 것으로 한정 할 수 있다.

이런 TLS 통신을 하기 위해서는 인증서 만들어야 하는 등의 다양한 작업이 필요하지만 Docker Machine을 사용하여 Docker 호스트를 작성한 경우에는 그 작업은 자동으로 이루어진다. 여기에서도 이 Docker Machine 자동 설정을 이용하여 TLS 통신을 한다. (참고 : 자동 설정을 사용하는 이유는 쉽게 TLS 통신을 체험 할 수 있기 때문이고, 높은 안전성이 보장되기 때문은 아니다.)

사전 준비

이상으로 설명한 것에 대해 여기에서 실제로 Docker Engine을 사용해 보고 더 깊게 이해를 보도록 하자. 개요는 다음과 같다.

  • 사전 준비
  • curl에 따르면 API 호출 (Unix 소켓 통신)
  • API 호출에 의한 “Hello World”(Unix 소켓 통신)
  • Docker CLI 설치
  • Docker CLI가 원격 연결 (TLS 통신)
  • 참고 : 프록시 인증서를 다시 작성

우선 이전과 마찬가지로 사전 준비로 Windows 10 , VirtualBox , PowerShell 을 준비한다.

또한 다음과 같이 Docker Machine을 사용하여 Docker 호스트를 작성한다.

PS > docker-machine create myhost

이 create명령을 실행하면 Docker 호스트 중 Docker 버전은 최신이다. 그러나 필자가 이용한 Docker 버전은 “v17.09.0-ce"이므로, 혹시 Docker 버전이 다르기 때문에 다음에 소개하는 내용이 수행 할 수 없을지도 모른다. 이 경우 다음과 같이 create명령의 --virtualbox-boot2docker-url 옵션에 버전을 지정하여 Docker 호스트를 작성한다.

PS> $url = 'https://github.com/boot2docker/boot2docker/releases/download/v17.09.0-ce/boot2docker.iso'
PS> docker-machine create --virtualbox-boot2docker-url $url myhost

Docker 호스트가 생성되면 로그인한다.

PS> docker-machine ssh myhost

로그인하면 Docker CLI를 사용하여 “Hello World"가있는 것을 확인합시다.

docker@myhost:~$ docker run hello-world
(중간 생략)
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

여기까지는 이전과 같다.

다시 로그를 읽어 보면, Docker CLI (Docker client)와 Docker 데몬 (Docker daemon)의 처리에 대해 차례로 설명되어 있다. 이 로그에는 적혀 있지 않지만, Docker CLI는 Docker 데몬과 상호 작용하는 Docker Engine API를 호출한다. Docker Engine API는 Docker CLI 않아도 호출 할 수 있다. 그래서 다음 curl을 사용하여 Docker Engine API를 호출하자.

curl에 따르면 API 호출 (Unix 소켓 통신)

curl은 널리 알려진 HTTP 등 다양한 통신을 할 수있는 도구이다. curl은 처음부터 Docker 호스트에 설치되어 있지만, 만약을 위해 curl 버전을 확인하자.

docker@myhost:~$ curl --version
curl 7.49.1 (x86_64-pc-linux-gnu) libcurl/7.49.1 OpenSSL/1.0.2h zlib/1.2.8
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

curl 버전 7.40.0 이상이면 된다. curl 버전 7.40.0에서 Unix 소켓을 사용할 수 있다. 다음과 같이 Unix 소켓을 사용하여 Docker Engine API를 호출하자.

docker@myhost:~$ curl --unix-socket /var/run/docker.sock http:/version
{
    "Version":  "17.09.0-ce",
    "ApiVersion":  "1.32",
    "MinAPIVersion":  "1.12",
    "GitCommit":  "afdb6d4",
    "GoVersion":  "go1.8.3",
    "Os":  "linux",
    "Arch":  "amd64",
    "KernelVersion":  "4.4.89-boot2docker",
    "BuildTime":  "2017-09-26T22:45:38.000000000+00:00"
}

--unix-socket 옵션에 지정되어 있는 /var/run/docker.sock이 Docker 소켓의 경로이다. http:/version는 Docker 버전 정보를 받아오는 API이다. 버전 정보는 JSON 형식으로 출력되고 있다. "ApiVersion": "1.32"라는 것이 API의 버전이다. 버전 1.32의 문서에는 다양한 API가 샘플과 함께 설명되어 있다. 그 내용들을 참고로 하면서, 다음은 “Hello World"를 출력해 보자.

API 호출에 의한 “Hello World”(Unix 소켓 통신)

먼저, 컨테이너를 만든다.

curl --unix-socket /var/run/docker.sock \
    -H "Content-Type: application/json" \
    -d '{"Image": "hello-world", "Tty": true}' \
    -X POST http:/containers/create
{"Id":"469a115ce858fc7ae41639dc3ec7bf354e88015cc98b2540a4c8a7598e01445e","Warnings":null}

이미지 이름이 "hello-world"이고 -d '{"Image": "hello-world", ...와 같은 식으로 JSON 형식으로 지정되어 있다. -X POST는 HTTP의 POST 메서드를 사용한다는 의미이다. http:/containers/create는 컨테이너를 생성하는 API이다.

출력 결과의 {"Id":"469a11...는 생성된 컨테이너의 ID이다. 이 ID를 이용하여 컨테이너를 시작한다.

docker@myhost:~$ curl --unix-socket /var/run/docker.sock \
    -X POST http:/containers/469a11/start

http:/containers/469a11/start이 컨테이너를 시작하는 API이다. 시작하는 컨테이너는 이러한 컨테이너 ID 앞에 숫자 문자(469a11)로 지정할 수 있다.

작성한 “hello-world"이미지 컨테이너는 시작할 때 로그를 출력하고 즉시 중지하는 컨테이너이다. 성공적으로 중지했는지 확인하자.

docker@myhost:~$ curl --unix-socket /var/run/docker.sock -X POST http:/containers/469a11/wait
{"StatusCode":0}

http:/containers/469a11/wait 컨테이너가 멈출 때까지 기다린 후 종료 코드를 StatusCode로서 돌려주는 API이다. StatusCode0이므로 컨테이너의 처리는 성공하였다.

컨테이너의 로그를 확인하자.

docker@myhost:~$ curl --unix-socket /var/run/docker.sock http:/containers/469a11/logs?stdout=1

Hello from Docker!
This message shows that your installation appears to be working correctly.
(이하 생략)

docker run 명령에 “Hello World"를 실행했을 때와 같은 로그가 출력되어 있아. 호출 API는 조금 다르지만 docker run 명령도 이와 같이 Docker Engine API를 통해 Docker 데몬과 상호 작용을 하고 있다.

Docker CLI 설치

자, 다음은 Docker CLI가 원격 연결(TLS 통신)을 수행하기 위해 Windows에 Docker CLI를 설치한다. 설치는 Docker Machine뿐만 아니라 바이너리 파일을 다운로드하여 Path 설정을 하기만 하면 된다.

Docker CLI의 Windows 64 비트 버전의 바이너리 파일은 여기에서 다운로드 할 수 있는데, 만약 표시가 연결되지 않는다면, 공식 문서를 참조해라.

Docker CLI 버전은 Docker 호스트 Docker 버전이 되도록 맞춘다. 버전이 다르면 정상적으로 작동하지 않을 가능성이 높다. 버전이 v17.09.0-ce는 파일 이름이 “docker-17.09.0-ce.zip"이다.

zip 파일을 다운로드 한 후 압축을 풀고 안에 들어있는 docker.exe 파일을 환경 변수 Path에 추가한다. PowerShell에서 Path 설정 방법에 대해서는 이전을 참고해라.

Path를 설정 한 후 다음 명령을 실행한다.

PS> docker version
Client:
 Version:      17.09.0-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:40:09 2017
 OS/Arch:      windows/amd64
error during connect: Get https://%2F%2F.%2Fpipe%2Fdocker_engine/v1.32/version:
open //./pipe/docker_engine: The system cannot find the file specified.
In the default daemon configuration on Windows, the docker client must be run elevated to connect.
This error may also indicate that the docker daemon is not running.

출력된 내용중 상단에 `Client:에 Docker CLI 버전 정보가 출력되어 있으면 설치가 완료된거다.

하단에는 오류 메시지가 출력되고 있다. 다음 원격 연결을 설정하는 것으로, 하단에는 Docker 호스트 측의 정보가 출력되게 된다.

Docker CLI가 원격 연결 (TLS 통신)

원격 접속을하기 위해서는 대상 Docker 호스트 정보를 설정해야 한다. 다음은 설정 방법을 2가지 소개한다.

(1) docker 옵션을 설정하는 방법

PowerShell에서 다음 Docker Machine 명령을 실행하여 보자.

PS> docker-machine config myhost
--tlsverify
--tlscacert="C:\\Users\\Taro\\.docker\\machine\\machines\\myhost\\ca.pem"
--tlscert="C:\\Users\\Taro\\.docker\\machine\\machines\\myhost\\cert.pem"
--tlskey="C:\\Users\\Taro\\.docker\\machine\\machines\\myhost\\key.pem"
-H=tcp://192.168.99.100:2376

이 config명령은 원격 연결을 위한 docker 옵션을 출력하는 명령이다. --tls로 시작하는 옵션은 Docker Machine이 자동으로 생성된 인증서의 경로 등이 지정되어 있다. -H=tcp://192.168.99.100:2376는 TLS 통신을 허용 “myhost"의 IP 주소와 포트 번호이다.

이 옵션을 복사하고 다음과 같이 docker version명령에 추가하고 실행하자. (각 행의 끝에 붙어있는 “`“는 백틱(역 따옴표)에서 PowerShell에서는 긴 명령을 여러 줄로 나누어 쓰고 싶을 때 사용한다.)

PS> docker --tlsverify `
--tlscacert="C:\\Users\\kimkc\\.docker\\machine\\machines\\myhost\\ca.pem" `
--tlscert="C:\\Users\\kimkc\\.docker\\machine\\machines\\myhost\\cert.pem" `
--tlskey="C:\\Users\\kimkc\\.docker\\machine\\machines\\myhost\\key.pem" `
-H=tcp://192.168.99.100:2376 version

Client:
 Version:      17.09.0-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:40:09 2017
 OS/Arch:      windows/amd64

Server:
 Version:      17.09.0-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:45:38 2017
 OS/Arch:      linux/amd64
 Experimental: false

원격 연결에 성공하여 “Server :“정보가 출력되었다.

그러나 docker 명령을 실행할 때마다 매번 같은 긴 옵션을 붙이는 것은 가급적 피해 싶다. 그래서 다음과 같이 환경 변수를 설정하자.

(2) 환경 변수를 설정하는 방법

원격 연결에 필요한 환경 변수는 Docker Machine과 PowerShell을 사용하여 다음과 같이 한 줄로 설정할 수 있다.

PS> docker-machine env myhost | Invoke-Expression

이 명령을 실행 한 후 계속 같은 PowerShell에서 docker version및 버튼 docker run hello-world을 실행하여 보자. 버전 정보가 출력되고 “Hello World"를 실행할 수 있어야 한다.

그러면, 이 명령은 도대체 무엇을 하고있는 것일까요? 분할하여 살펴 보자.

먼저 다음과 같이 파이프 라인 기호 " |“왼쪽의 명령을 실행한다.

PS> docker-machine env myhost
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.99.100:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\kimkc\.docker\machine\machines\myhost"
$Env:DOCKER_MACHINE_NAME = "myhost"
$Env:COMPOSE_CONVERT_WINDOWS_PATHS = "true"
# Run this command to configure your shell:
# & "C:\Users\kimkc\Scripts\docker-machine.exe" env myhost | Invoke-Expression 

$Env:문자열이 몇 줄 출력되어 있다. $Env:는 이전에 언급 된 바와 PowerShell에서 환경 변수이다. 변수 이름과 설정 값에서 알 수 있듯이 이들은 TLS 통신에 대한 환경 변수이다. 이렇게 Docker Machine의 env명령은 원격 연결하려는 Docker 호스트에 대한 환경 변수를 문자열로 출력해 준다.

단, env명령은 단순히 문자열을 출력 해주는 것에 지나지 않는다. 출력된 문자열을 PowerShell 명령으로 실행하지 않으면 환경 변수는 설정되지 않는다.

문자열을 실행 해주는 것이 PowerShell의 Invoke-Expression 명령(약어 iex)이다. 즉, docker-machine env myhost | Invoke-Expression이 Docker Machine의 env명령에서 출력된 문자열을 PowerShell의 Invoke-Expression 명령으로 실행하여 원격 연결에 필요한 환경 변수를 설정하고 있었던 것이다.

이처럼 Docker CLI는 환경 변수에 의해 연결을 전환 할 수 있다. 이번에 작성한 “myhost"이외에도 여러 Docker 호스트를 만들어 시험해 보면 좋을 것이다.

이상에서 Docker CLI가 원격 연결 (TLS 통신) 할 수 있게 되었다. 이하에서는 추가로 원격 연결 곤란할 때의 대처법을 2가지를 소개하겠다.

보충 1 : 프록시

env 명령을 사용하여 환경 변수를 설정해도 다음과 같이 오류가 발생할 수 있다.

PS> docker-machine env myhost | Invoke-Expression
PS> docker version
(중략)
error during connect: Get https://192.168.99.100:2376/v1.32/version: Service Unavailable

원인의 하나로서, 회사나 학교의 HTTP 프록시하여 Docker 호스트의 IP 주소(192.168.99.100)까지 도달할 수 없을 때 발생한다. 이 경우 다음과 같이 --no-proxy 옵션을 추가하자.

PS> docker-machine env --no-proxy myhost
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.99.100:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\kimkc\.docker\machine\machines\myhost"
$Env:DOCKER_MACHINE_NAME = "myhost"
$Env:COMPOSE_CONVERT_WINDOWS_PATHS = "true"
$Env:NO_PROXY = "192.168.99.100"
# Run this command to configure your shell:
# & "C:\Users\kimkc\Scripts\docker-machine.exe" env --no-proxy myhost | Invoke-Expression

--no-proxy 옵션을 추가하여 아래에서 세 번째 줄 $Env:NO_PROXY = "192.168.99.100"이 추가로 출력 되었다. $Env:NO_PROXY 프록시를 경유하지 않는 IP 주소를 설정하는 환경 변수이다. 이렇게 $Env:NO_PROXY에 “myhost"의 IP 주소를 지정하면 Docker CLI는 프록시를 경유하지 않고 “myhost” 원격 연결을 시도한다.

보충 2 : 인증서를 다시 작성

Docker Machine을 계속 사용하면 가끔 다음과 같은 오류 메시지가 출력될 수 있다.

PS> docker-machine env myhost | Invoke-Expression
Error checking TLS connection: Error checking and/or regenerating the certs:
There was an error validating certificates for host "192.168.99.101:2376":
x509: certificate is valid for 192.168.99.100, not 192.168.99.101
You can attempt to regenerate them using 'docker-machine regenerate-certs [name]'.
Be advised that this will trigger a Docker daemon restart which might stop running containers.

원인의 하나로서 인증서를 생성 할 때(Docker 호스트를 작성했을 때)의 IP 주소와 이번 Docker 호스트를 시작할 때 IP 주소가 다른 것을 생각할 수 있다. Docker Machine은 Docker 호스트를 시작할 때 IP 주소를 동적으로 할당하는 Docker 호스트를 여러 개 생성하고 이러한 오류가 자주 발생한다.

이 경우 오류 메시지에 표시되어 있는대로 regenerate-certs 명령으로 인증서를 다시 만들어 보다.

PS> docker-machine regenerate-certs myhost
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Waiting for SSH to be available...
Detecting the provisioner...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...

이제 다시 원격 접속을 할 수있게 될 것이다.

결론 : Docker Engine과 “assemble”

이번에는 Docker Engine의 구조에 대해 설명하였다. API 호출과 원격 연결을 통해 클라이언트 서버 모델이라고도 말할 수 Docker Engine의 구조를 체험 할 수 있었던 것이 아닐까 생각된다.

최후에 최근 Docker 사의 동향과 Docker Engine의 관계에 대해 간략하게 소개하고, 정리하려고 한다.

Docker Engine이라는 명칭이 명시적으로 사용된 것은 2014년 6 월 DockerCon이 처음이라고 말해도 좋을 것이다. 이 DockerCon는 libcontainer 과 libswarm 등 현재 개발되어 있는 구성 요소의 원류가 되는 요소도 발표되고 있다. 분명히 지금까지 “Docker"로 일괄로 부른 것을, 이 무렵부터 조금씩 구성 요소로 명확하게 구분 가려고 했던 것 같다.

이번에 소개한 Docker Engine의 세 가지 구성 요소도 각각 Docker의 진화와 함께 구성 요소로 모양을 명확하게 해 온 것이다. 그중 Docker 데몬은 또한 몇 가지 구성 요소로 나누어져 있다. 예를 들어 containerd는 Docker 데몬의 컨테이너에 대한 처리를 구성 요소로 잘라낸 것이다. 현재 containerd는 Cloud Native Computing Foundation(CNCF)라는 조직의 프로젝트로 개발이 진행되고 있다.

이러한 구성 요소화의 흐름은 2017년 4월에 DockerCon 2017에서 발표된 Moby 프로젝트에 따라 새로운 단계에 들어 섰다고 말할 수 있겠다.

Moby는 말하자면 나름대로의 Docker를 만들기 위한 프레임워크이다. Moby 프로젝트의 홈페이지에는 다음과 같이 적혀 있다.

An open framework to assemble specialized container systems without reinventing the wheel.

이 글에서 주목해야 할 것은 “assemble"라는 단어이다. “assemble"은 “수집하다”, ‘‘조립하다"라는 뜻이다. Moby는 다양한 구성 요소를 모아 Docker 같은 컨테이너 시스템을 조립하는 오픈 프레임워크라는 것이다.

Docker사는 향후 다양한 컨테이너 시스템을 “assemble"하는 수단으로 Moby를 제공하고 Moby을 활용해 뛰어난 형태로"assemble"한 컨테이너 시스템의 하나로서 Docker를 제공하고 가자라고 하고 있다. Docker를 중심으로하는 컨테이너 기술은 변화가 심하고 계속해서 새로운 제품이 등장해 오는데, 그 컴포넌트인가, 컴포넌트를 “assemble"한 성과인가의 관점에서 바라 보면 이해가 되지 않을까 생각된다.

4.8 - Docker 입문 | 7. 바인드 마운트 Hello Java

이번에는 Docker 바인딩 마운트 기능에 대해 설명한다. 또한 바인딩 마운트의 구체적인 예로서 Java Hello World 프로그램을 컴파일하고 실행하는 방법을 소개한다.

Docker 마운트 기능

‘마운트’라는 용어는 Linux 나 Windows 등 OS의 용어로 아시는 사람이 많을 것이다. 예를 들어 “하드 디스크를 탑재하는 것"이라고 말했다면 OS가 하드 디스크를 인식하고 사용할 수 있는 상태로 만드는 것을 의미한다.

Docker에서 “마운트"는 컨테이너 외부에있는 데이터를 컨테이너에서 사용할 수 있는 상태가 될 것을 의미한다. 207년 말에 공개된 “Docker v17.12.0-ce"는 다음의 세 가지 마운트 기능이 제공되고 있다.

  1. 바인드 마운트 (bind)
  2. 볼륨 마운트 (volume)
  3. 임시 파일 시스템 마운트 (tmpfs)

이번에 설명하는 “1. 바인드 마운트"는 Docker 호스트 파일이나 디렉토리를 사용할 수 있도록 하는 기능이다. 바인드 마운트를 하면 컨테이너의 외부에 있는 Docker 호스트 파일을 컨테이너 속에서 읽고 쓸 수 있게 된다. 바인드 마운트된 파일은 /home/var와 같은 경로를 이용하여 아래에서 컨테이너 안에 있는 파일처럼 사용할 수 있다.

“2. 볼륨 마운트"는 Docker 호스트 파일이나 디렉토리 중 Docker가 관리하고 있는 것을 사용할 수 있도록하는 기능이다. “3. 임시 파일 시스템 마운트"는 Docker 호스트에 파일로 저장하고 싶지 않은 데이터를 일시적으로 사용할 수 있도록하는 기능이다. 모두 이번 자세하게 설명하지는 않겠지만, 데이터의 이용 목적에 따라 각각을 구사하면 좋을 것이다.

마운트 개요

컨테이너의 격리성(isolation)

바인드 마운트 Docker의 초기부터 제공되는 기능이며 , 현재에도 잘 이용되고 있다. 바인드 마운트가 필요한 이유는 컨테이너의 특징 중 하나 인 격리성 (isolation)과 강하게 연관되어 있다.

일반적으로 컨테이너는 컨테이너 안에 있는 데이터만 사용할 수 있다. 어떤 컨테이너에서 다른 컨테이너에 있는 데이터와 Docker 호스트의 데이터를 사용할 수 없다. 예를 들어, 컨테이너에서 ls /home와 같은 명령어를 실행하면 출력되는 것은 컨테이너에 있는 /home의 정보만 표시된다. 다른 컨테이너의 /home와 Docker 호스트 /home의 정보는 전혀 표시되지 않는다. 그런 성격을 컨테이너의 격리성이라고 한다.

컨테이너는 파일이나 디렉토리를 격리할 뿐만 아니라 프로세스와 네트워크 등을 격리해 준다. Docker가 가상화 기술의 일종이라고 말하는 것은 그렇게 여러 가지를 격리하고 가상으로 독립적인 환경을 만들어주는 것이다.

격리성은 Docker에게 매우 중요한 특성이다. 격리성을 높다는 것은 Docker 호스트 등 주변 환경에 대한 의존도를 낮추는 등 다양한 장점이 있다. 그러나 그 반대로 격리 가능성이 높은 것으로 불편을 느끼는 경우도 있다.

예를 들어, 이번에 다르게 될 Java Hello World 프로그램처럼 작은 파일을 생성하고 컨테이너로 이용하는 경우를 생각해 보다. Docker 호스트 파일을 작성한 경우 컨테이너 안에서 그 파일을 읽거나 쓸 수 없다. 컨테이너에서 파일을 작성하면 읽고 쓰기는 당연히 할 수 있지만 평소 친숙한 텍스트 에디터를 컨테이너 안에 있는 것은 없다. 또한 컨테이너에서 만든 파일은 컨테이너를 삭제하면 함께 삭제되어 버린다. 삭제되기 전에 docker container cp명령을 실행하고 파일을 컨테이너 밖으로 복사 할 수 있지만, 왠지 귀찮은 느낌이 든다.

그런 상황을 바인드 마운트 는 격리성을 낮추므로써 가능하게 해준다. 일반적으로 컨테이너 속에서 읽고 쓸 수 없는 Docker 호스트 파일을 바인드 마운트된 것에 한하여 특별히 읽고 쓸 수 있도록 해주는 것이다.

사전 준비

그럼 여기에서 Java Hello World 프로그램을 예로 바인드 마운트의 구체적인 사용법에 대해 살펴 보겠다. 개요는 다음과 같다.

  • 사전 준비
  • 격리성 실험 : 바인드 마운트하지 않으면 어떻게 될까
  • 바인드 마운트 기본 : mount 옵션
  • Java 컴파일 : mount 옵션
  • Java 실행 : workdir 옵션 및 mount 옵션
  • alias의 활용
  • Windows에서 파일의 바인딩 마운트
  • volume 옵션

우선 사전 준비로 Docker 호스트를 준비한다. 여기에 내용은 Docker Machine v0.12.2를 사용하여 Windows 10의 VirtualBox 만든 Docker 호스트에서 검증하고 있다. Docker Machine 사용에 대해서는 “Docker Machine으로 Windows에 Docker 포스트 만들기“를 참고해라.

Docker 버전 v17.06 이상으로 해라. 이후 --mount라는 옵션을 사용하기 때문이다. 본 기사의 Docker 버전은 “v17.12.0- ce"이다.

Docker 호스트가 준비되면 Java 컨테이너를 움직여 보자. 이번에는 Docker의 공식 이미지 인 openjdk 이미지 를 사용한다.

다음 명령을 실행하여 Java 버전을 확인한다.

$ docker run --rm openjdk:9 java --version
openjdk 9.0.1
OpenJDK Runtime Environment (build 9.0.1+11-Debian-1)
OpenJDK 64-Bit Server VM (build 9.0.1+11-Debian-1, mixed mode)

openjdk:9 이미지에서 생성된 컨테이너에서 java --version라는 명령이 실행되고 정보가 출력되었다. 따라서 이번에는 Docker의 공식 이미지인 openjdk 이미지 중에 JDK 버전 9가 포함된 이미지를 사용한다.

위의 명령에서 --rm 옵션을 지정하고 있는 것에 주목하자. --rm는 컨테이너가 멈추면 자동으로 삭제하는 옵션이다. 이후 여러번 Java 컨테이너를 생성하고 시작하는데, 아무것도하지 않으면 컨테이너 차례 차례로 쌓여 가기 때문에 이렇게 --rm옵션으로 자동으로 제거한다.

마지막으로, Docker 호스트에 다음과 같은 Java 파일을 작성한다.

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

이를 /home/docker/Hello.java로 저장한다. 반복이 되겠지만, 이 “Hello.java"는 Docker 호스트에 작성한다.

사전 준비는 완료되었다.

격리성 실험 : 바인드 마운트하지 않으면 어떻게 될까

그럼, 먼저 소개 바인드 마운트하지 않으면 어떻게 되는지 격리성이란 어떤 것인지 확인해 보자.

다음 명령을 실행하여 보자.

$ ls /home/docker/Hello.java
/home/docker/Hello.java
$ docker run --rm openjdk:9 ls /home/docker/Hello.java
ls: cannot access '/home/docker/Hello.java': No such file or directory

첫 번째의 ls는 Docker 호스트에서 실행하고 있으므로 Docker 호스트의 /home/docker 디렉토리에 있는 Hello.java이 보이고 있다.

두 번째의 ls는 컨테이너에서 실행하고 있기 때문에, 컨테이너 안의 /home/docker 디렉토리를 찾아간다. 컨테이너에 있는 디렉토리는 격리되어 있기 때문에 Docker 호스트의 Hello.java를 찾을 수 없다. (원래 openjdk 이미지에서 만든 컨테이너에는 /home 디렉토리는 있지만, /home/docker 디렉토리는 없다.)

또한 실험해 보자. 이번에는 cat 명령을 실행하여 Hello.java 내용을 출력해 보자.

$ cat /home/docker/Hello.java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

$ docker run --rm openjdk:9 cat /home/docker/Hello.java
cat: /home/docker/Hello.java: No such file or directory

역시 두 번째의 cat은 컨테이너에서 실행중인 때문에 Docker 호스트의 Hello.java를 찾을 수 없다.

마지막으로, 컨테이너에서 Java 컴파일 할 수 있는지 시험해 보자.

$ docker run --rm openjdk:9 javac Hello.java
javac: file not found: Hello.java
Usage: javac <options> <source files>
use --help for a list of possible options

역시 오류가 출력되었다. 컨테이너의 javac 명령을 실행하고 Hello.java 컴파일하려고 했지만, Docker 호스트의 Hello.java은 찾을 수 없다.

억지로 공식 이미지에서 JDK의 컨테이너를 쉽게 만들 수 있지만 이대로는 Hello.java를 컴파일 할 수 없다.

[컨테이너의 격리성]

바인드 마운트 기본 : mount 옵션

그러면 바인딩 마운트를 사용하여 Hello.java 컨테이너에서 사용할 수 있도록 한다.

바인드 마운트 설정은 --mount 옵션으로 한다. 다음과 같이 바인딩 마운트를 설정하고 cat명령을 실행한다.

$ docker run --rm --mount type=bind,src=/home/docker,dst=/home/test openjdk:9 cat /home/test/Hello.java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

Hello.java 내용이 출력되었다! 컨테이너에서 실행한 cat 명령으로 Docker 호스트의 Hello.java가 표시되는 것이다.

--mount 옵션을 살펴 보자. --mount 옵션은 ‘키=값’의 형식으로 마운트 설정을 설명한다. “키=값"은 쉼표로 구분한다. 쉼표의 좌우에 공백을 넣지 않도록 주의해라. 각 “키=값"의 의미는 다음과 같다.

  • type=bind
    • 탑재 유형이다. 사용할 수 있는 값은 처음에 소개한 세가지 bind, volume, tmpfs 이다. 여기에서는 바인드 마운트를 수행하기 위해 bind지정하고 있다.
  • src=/home/docker
    • 마운트 Docker 호스트의 디렉토리이다. 여기에서는 Hello.java이 들어있는 /home/docker로 지정하고 있다. 하나에 대한 /home지정도 좋다. 이 경우 /home 아래의 /home/dockerHello.java도 함께 마운트되었다. src 대신에, source 라고 써도 같은 의미이다.
  • dst=/home/test
    • 마운트 Docker 호스트 디렉토리, 컨테이너 속에서 경로이다. 컨테이너 안에 /home/test 라는 경로에서 위에 src에 지정된 /home/docker를 사용할 수 있다. /home/test 디렉토리는 원래의 용기 안에 존재도 존재하고 있지 않아도 괜찮다. dst 대신에 destinationtarget라고 써도 같은 의미이다.

바인드 마운트

Java 컴파일 : mount 옵션

바인드 마운트 할 수있게 되었으므로, Hello.java을 컴파일하여 보다.

다음 명령을 실행하십시오.

$ docker run --rm --mount type=bind,src=/home/docker,dst=/home/test openjdk:9 javac /home/test/Hello.java

이제 컴파일이 되었다. 확인하자.

$ ls /home/docker/Hello*
/home/docker/Hello.class  /home/docker/Hello.java

Hello.class가 생성되어 있다. 컴파일 성공이다.

바인드 마운트를 수행하여 Docker 호스트의 Java 파일을 컨테이너로 컴파일하여 클래스 파일을 Docker 호스트에 출력 할 수있는 것을 알 수 있었다.

Java 실행 : workdir 옵션 및 mount 옵션

그런 다음 Hello.class을 실행하자.

Hello.class를 실행하는 명령 java Hello합니다. 일단 방금 컴파일 할 때의 javac …명령을 java Hello에 대체 실행하자.

$ docker run --rm --mount type=bind,src=/home/docker,dst=/home/test openjdk:9 java Hello
Error: Could not find or load main class Hello
Caused by: java.lang.ClassNotFoundException: Hello

ClassNotFoundException가 발생하였다. Hello.class이 없는 것 같다.

클래스 파일이 없는 경우의 해결 방법은 여러 가지가 있지만, 여기에서는 --workdir 옵션(약어 -w)를 사용하여 java명령을 실행하는 디렉토리를 바꿔 보자.

--workdir 옵션은 컨테이너에서 어떤 디렉토리에서 작업을 수행할지 여부를 지정할 수 있는 옵션이다. 그렇게 작업을 수행할 디렉토리를 다음에서 작업 디렉토리 라고 한다.

--workdir 옵션을 지정하지 않으면 사용하는 이미지의 설정에 따라 작업 디렉토리가 결정된다. 방금 ClassNotFoundException이 발생한 명령의 작업 디렉토리가 무엇이었을까, pwd 명령으로 확인 해보자.

$ docker run --rm --mount type=bind,src=/home/docker,dst=/home/test openjdk:9 pwd
/

작업 디렉토리는 루트 디렉토리(/) 였다. Hello.class이 놓여있는 위치는 루트 디렉토리가 아니라 dst지정된 /home/test 디렉토리이기 때문에 ClassNotFoundException이 발생한 것이다. java Hello를 실행하는 작업 디렉토리를 루트 디렉토리가 아닌 /home/test 디렉토리로 이동하면 Hello.class 찾을 수 있을 것 같다.

그래서 다음과 같이 --workdir 옵션을 /home/test으로 지정하여 보자.

$ docker run --rm --mount type=bind,src=/home/docker,dst=/home/test --workdir /home/test openjdk:9 java Hello
Hello, World

수행 할 수 있었다. “Hello, World” 성공이다!

--workdir 옵션은 바인드 마운트 및 Java 컨테이너뿐만 아니라 자주 사용하는 유용한 옵션이다. 이번처럼 있어야 할 파일을 찾을 수 없어서 곤란 때 등에 기억 사용해 보면 좋을 것이다.

alias의 활용

바인드 마운트는 유용하지만, 좀 명령이 길었다. 다음과 같이 Linux의 alias 명령으로 짧게 해보자.

$ alias java='docker run --rm --mount type=bind,src=/home/docker,dst=/home/test --workdir /home/test openjdk:9 java'

$ java Hello
Hello, World

두 번째 명령 java Hello의 java는 alias이므로, 실제로는 컨테이너가 동작한다. 이와 같이 alias를 활용하면 마치 로컬에 설치되는 도구처럼 컨테이너를 사용할 수 있다.

Windows에서 파일의 바인딩 마운트

Docker Machine으로 Windows에 Docker 포스트 만들기 페이지처럼 Docker Machine을 사용하여 Windows에서 VirtualBox에 Docker 호스트를 작성하는 경우 Windows에서 파일을 바인드 마운트 할 수 있다.

무슨 뜻인지 다음과 같이 Docker 호스트의 /c/Users폴더를 바라 보면 직관적으로 이해할 수 있다.

$ ls /c/Users
All Users     Default User  Public/
Default/      kimkc/     desktop.ini         

귀하의 Windows 시스템에 따라 다르지만 대략 위와 같은 비슷하게 출력 결과가 표시될 것이다. 어쩐지 본 적이 있는 폴더가 나열되어 있지 않은가? Windows 사용자 폴더이다.

c/Users 폴더는 Docker Machine이 자동으로 설정해주는 VirtualBox 공유 폴더이다. 공유 폴더 덕분에 Windows 사용자 폴더를 Docker 호스트의 폴더로 사용할 수있는 상태가 되어 있는 것이다. 이 공유 폴더를 예 --mount src=/c/Users/kimkc처럼 바인딩 마운트하면 Windows 파일이 바인드 마운트된 것처럼 이용할 수 있다는 것이다.

volume 옵션

마지막으로 --volume옵션(약어 -v)에 대해 살펴 보도록 하다.

이번에 소개한 바인딩 마운트와 대략 같은 처리를 –volume옵션을 사용하여 수행 할 수 있다. --volume--mount보다 훨씬 이전부터 존재하고 오랫동안 사용할 수있는 옵션이다. 여기에서는 설명하지 않겠지만, --volume 옵션의 샘플 코드와 해설 기사가 다수 존재하기 때문에 검색 해 보면 좋을 것이다.

그런데 Docker사로는 앞으로 마운트 처리를 배우는 사람은 더 다루기 쉬운 --mount옵션을 이용할 것을 권장하고 있다. 필자는 --mount옵션의 사용법을 기억하는 경우 Docker Compose를 사용하여 여러 컨테이너 배포 페이지에서 소개한 Docker Compose 및 클러스터링 기능의 Swarm, 그리고 --volume 옵션을 이해하기 쉬울 거라 생각한다. 따라서 처음에는 --mount 옵션에서 학습 할 것을 권장한다.

결론

이번에는 Docker 바인딩 마운트 기능에 대해 설명하였다. 또한 바인딩 마운트의 구체적인 예로서 Java Hello World 프로그램을 컴파일하고 실행하는 방법을 소개하였다.

바인드 마운트는 컨테이너의 특징 인 고립을 굳이 내려 컨테이너를 편리하게 이용할 수 있도록하는 기능이라고 할 수 있다. 컨테이너의 장점을 크게 해치지 않도록주의하면서 바인딩 마운트를 잘 이용하여 컨테이너를 활용할 수 있도록 하자.

5 - Windows

5.1 - 윈도우즈와 UNIX 계열은 줄바꿈 개행 문자가 다르다.

OS별로 개행 문자

윈도우와 UNIX 계열의 OS는 줄바꿈을 처리하는 방식이 다르다. 개행문자의 차이인데 윈도우는 CR+LF, UNIX 계열의 OS(LINUX 등)는 LF를 사용한다. \r\n, \n의 차이로 이해하면 더 쉽게 접근이 가능할 것 같다.

기호의 이미는 라래와 같다.

  • \r : CR (Carriage Return) 그 라인의 맨 앞으로 간다.
  • \n : LF (Line feed) 다음 줄로 간다.

OS별로 개행 문자는 아래와 같다.

  • DOS(Windows) : \r\n
  • UNIX 혹은 Linux : \n
  • Mac : \r, 이것만으로 CR+LF을 의미한다.

OS별로 개행 문자 문제 해결 방법

이러한 문제로 인해서 리눅스에서 작성한 텍스트 파일을 윈도우에서 열었을 때 줄바꿈이 정상적이지 않아 제대로 볼 수 없는 경우가 많은데 이러한 문제를 해결하는 방안에 대해서 알아 보겠다.

윈도우 - 워드패드

윈도우 시스템에서 시작 - 보조프로그램에 워드패드라는 프로그램이 있다.

이 워드패드라는 프로그램으로 리눅스에서 작성된 텍스트 파일을 열게되면 줄바꿈이 정상적으로 되어 보여지게 된다.

이 상태에서 ‘다른 이름으로 저장’ 기능을 사용하게 되면 파일 저장 경로와 이름을 지정할 수 있는 창이 뜨게 되는데, 아래 부분의 ‘파일 형식’에서 ‘텍스트 문서 - MS-DOS형식’을 선택할 수 있다.

바로 이 것을 선택하여 저장하게 되면 줄바꿈에 대한 처리를 윈도우의 CR+LF로 처리하여 저장하게 되므로 윈도우에서도 정상적으로 사용할 수 있는 텍스트 문서가 생성되게 된다.

이 방법으로도 정상적으로 처리가되지 않는다면 역시 문제의 시발점인 리눅스에서 처리하는 것이 가장 빠른 방법일 것이다.

UNIX 계열 OS - VIM

VIM으로 문제의 파일을 연다.

리눅스의 VIM에서는 윈도우의 파일을 유닉스 형태로, 유닉스의 파일을 윈도우 형태로 변환을 자유자재로 할 수 있는데 우선은 윈도우의 파일을 유닉스 형태로 변환하는 것을 보겠다.

:set ff=unix

자, 이제 저장만 하면 끝. 매우 간단하다.

유닉스의 파일을 윈도우 형태로 변환하는 것도 역시 간단하다.

:set ff=dos

정리

이러한 편집기를 사용할 상황이 되지 않는다면 FTP에서 다운로드 받을 때 애초에 ASCII로 다운을 받아서 자동으로 변환되도록 하는 방법이 있다. 그리고 마지막으로 \r\n\n에 대한 처리를 하는 매우 간단한 팁으로 \r\n를 무조건적으로 \n으로 치환하여 \n에 대한 처리만을 행하면 될 것이다.

5.2 - 윈도우즈 Hyper-V

가상화?

일반적으로 메모리나 하드 디스크 등의 하드웨어에 OS가 구동한다. 이러한 하드웨어를 소프트웨어로 구동하는 것으로, OS에서 다른 컴퓨터를 만들어 낼 수 있다.

가상화의 장점

  • 물리적 서버 대수를 줄임으로써 공간 절약/에너지 절약/비용 절약 할 수 있다.
  • 서로 다른 OS 환경을 구축 할 수 있다.
  • 환경을 준비하는 비용과 시간의 절감 된다.

가상화의 단점

  • 오버 헤드(추가 처리)가 하기에에 하드웨어에 크게 의존하는 응용 프로그램이 제대로 작동하지 않을 수 있다.

Hyper-V 이란?

Microsoft 사에서 제공하는 가상화 기술이다.

Hyper-V 특징

Hyper-V의 특징은 크게 2가지가 있다.

  • Windows server의 기능이다.
    • Windows 마찬가지로 Microsoft 사가 제공하고 있기에, Windows Server가 있으며 추가 비용이 없고, 사용이 간단하다.
  • 하이퍼 바이저 형 가상화 기술이다
    • 호스트 형 가상화 기술 (Virtual Server)와 달리 관리 OS에서와 마찬가지로 하이퍼 바이저에서 동작하기 때문에, 호스트 형에 비해 더 빠르게 작동한다.

6 - 그밖에

6.1 - 컴퓨터학 개론

컴퓨터의 개요

  • 사람을 대신하여 복잡한 연산을 수행하는 전자계산기
  • 대용량의 데이터를 보존 관리할 수 있다.

컴퓨터의 특징

  • 신속성: 대량의 데이터를 연산처리 할 수 있다. 최근 컴퓨터는 초당 수십억번의 산술연산작업을 수앵한다.
  • 신뢰성: 컴퓨터는 많은 데이터 처리와 함게 오류 없는 신뢰성을 보장해 주고 있다. 이는 컴퓨터가 사람의 업무를 대신하는데 없어서는 안 될 요소이다.
  • 정확성: 반도체 기술의 비약적인 발전으로 컴퓨터의 정확성은 날로 높아져 가고 있다.
  • 데이터의 보존: 각종 데이터를 보존하기 위해 기억장치들의 개발로 상단한 분량의 데이터를 작은 공간에 축적 보존할 수 있다.
  • 경제성: 대용량 데이터를 빠르게 처리함으로서 사람이 하는 것에 비하여 시간과 비용을 절감을 가져온다.

PC(Personal Computer, 개인용 컴퓨터)

초기 컴퓨터는 개인의 독자적인 사용을 전제하지 않고 공동의 이익을 위한 목적으로 개발되었으며 이에 따라 중앙처리부와 기억장치를 가진 중앙 컴퓨터와 사용 자를 위한 단말기로 구분되었다. PC는 개인의 독자적인 사용을 전재로 하여 개발된 컴퓨터로서 컴퓨터 갖춰야할 중앙처리부, 기억장치, 입출력장치를 하나의 단일화 된 제품으로 제작된 것이다

하드웨어와 소프트웨어

하드웨어

하드웨어는 물리적인 장치를 의미한다. 컴퓨터에는 CPU, 메모리, 디스크드라이브, 입출력장치 등 각종 하드웨어들이 존 재하고 있으며 이들은 소프트웨어의 명령을 받아 동작한다.

소프트웨어

소프트웨어는 컴퓨터에서 동작시키고 업무를 수행하는 프로그램들을 의미한다. 운영체제, 게임, 그래픽 프로그램, 교육용 프로그램, 업무용 프로그램 등이 이에 속한다.

기본 용어

bit(비트)와 Byte(바이트)

컴퓨터는 모든 자료를 0과 1로 표현하는 디지털 형식의 전기신호를 사용한다. 디지털이란 전기가 흐르는 상태 “1"과 흐르지 않는 상태 “0” 이라는 두 가지 전기 적인 상태만으로 데이터를 표현하는 것이다. 바로 이것이 컴퓨터에서 이야기하는 데이터 표현의 최소단위인 bit이다. 즉, 1bit로 표현 가능한 데이터는 1과 0이라는 두 가지뿐이다. 그러나 이것만으로 사람이 사용하는 문자를 컴퓨터의 데이터화시 키기는 역부족이다. 그래서 2개의 전기신호를 조합하면 00, 01, 10, 11이라는 4가 지의 자료를 표현할 수 있다. 그러나 이 역시 사람의 문자를 표현할 수 없다. 그래서 8bit를 조합하게 되는데 8bit를 조합하는 경우 모두 256가지의 데이터 표현 이 가능해진다. 이것을 1Byte라 한다. 결국 이것이 우리가 사용하는 문자(영문자) 하나를 표현하는 데이터 량이 되는 것이다. 1Byte는 8bit로 구성된다.

버스

컴퓨터에서 버스란 데이터를 전달하기 위한 전송통로를 의미한다. 이 통로의 구성 형태에 따라 컴퓨터의 종류를 구분하고 한다.CPU와 주변기기 사이에 한 번에 주고 받을 수 있는 데이터 폭을 의미한다. 8bit 를 기본으로 하며 16bit => 32bit => 64bit로 발전한다.

컴퓨터의 역사

최초의 컴퓨터 에니악

1944년 하버드 대학 교수인 에이컨 이 IBM 사의 후원을 얻어 우리가 최초의 컴퓨터라 부르는 ““MARK-1"을 제작하였다. “MARK-1"은 진정한 컴퓨터라 할 수 없었고 1946년 미국의 펜실베니아 대학에서 머클리와 에커트가 탄도표나 일기 예보, 원자 에너지 계산, 우주 광선 연구 등에 쓰이는 군사용 컴퓨터를 개발하였는데, 이것이 10진수 체계를 사용한 에니악(ENIAC) 이었다.

에니악은 진공관을 사용하여 계산할 수 있게 만든 것인데, 무려 18,000개의 진공 관과 6,000개의 스위치가 달려 있어 크기도 크지만 조작하기도 무척 힘든 컴퓨터 였다. 게다가 프로그램의 호환성이 없어 프로그램을 바꿀 때마다 그 많은 스위치의 연결을 처음부터 다시 해야 했다.

프로그램 내장방식의 에드삭

1949년 모리스 윌크스는 최초의 프로그램을 내장한 에드삭(EDSAC)을 완성하였, 1951년에는 노이만에 의해서 다시 2진수 체계를 사용한 에드박(EDVAC)이 라는 컴퓨터가 개발되었다. 또한 IBM사는 보조 기억장치로 자기테이프를 사용하는 UNVAC 1을 개발하여 미국의 인구 통계국에 설치하였다.

컴퓨터의 세대 구분

세대구분 년대 중앙처리장치 주기억장치 프로그래밍언어
1세대 1946~1957 진공관 자기드럼어셈블러램
2세대 1958~1964 트랜지스터 자기코어 포트란, 코볼램
3세대 1965~1974 IC 자기디스크 파스칼, 베이직램
4세대 1975년대 이후 LSI 반도체 현재의 각종 프로그램램
5세대 현재 VLSI 반도체 현재의 각종 프로그램

PC의 구조

중앙처리장치(CPU)

  • 컴퓨터의 각 장치들을 동작시키고 정상적인 동작을 위한 제어 역할을 수행하는 제어장치를 내장하고 있다.
  • 각종 연산 데이터를 처리하는 연상장치를 내장하고 있다.
  • 일시적인 자료의 저장을 위한 레지스터를 내장하고 있다.
  • 컴퓨터의 성능을 좌우하고 기종을 결정짓는 요소이다.

입력장치

  • 사용자로부터의 명령과 데이터를 입력받는 장치 키보드, 마우스 등이 이에 속한다.

출력장치

  • 컴퓨터가 처리한 결과를 사용자에게 전달하는 역할을 수행한다. 모니터, 프린터 등이 이에 속한다.

기억장치

  • 운영체제와 각종 프로그램이 설치되어 있으며 사용자들에 의하여 작성되는 데이터를 보존하는 장치이다.
  • 하드디스크, CD-ROM, CD-RW등이 이에 속한다.

주변기기

  • 컴퓨터의 기본적인 동작과 운영에는 필요하지 않으나 필요성에 의하여 추가로 설 치되는 장치를 주변기기이라고 한다.
  • 사용자의 편리성을 향상시킬 수 있다.
  • 랜카드, 사운드카드, 마우스, 프린터, 조이스틱 등이 이에 속한다.

제어기

  • 각 장치 간에 원활한 데이터의 흐름을 관장하고 에러를 검출한다.
  • 주변기기의 접속형식을 결정짓는 요소이다.
  • 하드웨어적인 형태로 존재하는 경우는 “컨트롤러“라는 용어를 사용한다.
  • 소프트웨어의 형식으로 존재하면 하드웨어를 동작시키기 위하여 설치하는 프로그램을 “드라이버”이라고 한다.

중앙처리장치(CPU)

  • 중앙처리장치 (Central Processing Unit)컴퓨터의 각 장치를 운영하는 명령을 내리며 동작을 감시하는 제어기능을 내장하 고 있다.
  • 산술 논리 연산장치를 내장하여 연산기능을 수행한다.
  • 컴퓨터의 기종을 결정짓는다.
  • 컴퓨터의 성능을 결정짓는다.

실행 유닛(Eu: Execution Unit)
실행 유닛은 마이크로프로세서의 각 명령어를 수행하는 유닛이다. 실행 유닛에는 ALU(Arithmetic Logic Unit)와 제어 유닛(CU:Control Unit), 레지스터로 구성된다. ALU에서는 덧셈이나 비교 연산과 같은 산술 연산, 논리연산을 수행한 후 중간 결과를 레지스터에 보관한다.

명령어 유닛(Instruction Unit)
명령어 유닛(Instruction Unit)은 메모리에서 가져온 명령어를 실행유닛에서 정확 히 수행할 수 있도록 제어하는 유닛이다. 이때 제어 유닛은 ALU나 레지스터들이 잘 동작되도록 한다.

어드레싱 유닛(Addressing Unit)
어드레싱 유닛은 CPU가 메모리나 입출력 장치에서 데이터를 읽거나 쓸 때, 메모리나 입출력 어드레스를 만들어 주는 유닛이다.

버스 인터페이스 유닛(Bus Interface Unit)
버스 인터페이스 유닛은 어드레스, 데이터, 컨트롤 버스를 통해서 마이크로프로세 서 외부와 연결시켜 주는 유닛이다.

Cache 메모리에 대한 이해

캐시란 속도가 다른 두 장치 사이에 위치하는 임시 기억장치로서 장치간의 데이 터 액세스 속도를 향상시키는 구실을 한다.반복적인 액세스에서 처리 속도를 향상시킨다.

캐시가 적용되지 않은 경우

  1. TEST.EXE라는 프로그램을 실행한다.
  2. (1) 보조기억장치(하드디스크)로부터 (3) 주기억장치로 TEST.EXE라는 프로그램을 불러들인다.
  3. 프로그램을 종료하면 (3)에 로드된 프로그램은 사라진다.
  4. 다시 같은 프로그램을 실행한다.
  5. 그러면 또 다시 (1)에서 (3)으로 프로그램을 불러들인다. 이 경우 사용자는 매번 실행 할 때마다 (1)로 부터 프로그램이 읽어지는 시간동 안 기다려야한다.

캐시가 적용된 경우

  1. TEST.EXE를 실행한다.
  2. (1)에서 (3)으로 프로그램을 불러들이면서 동시에 (2)에도 기록된다.
  3. 프로그램을 종료하면 (3)에 로드된 프로그램은 사라진다. 그러나 (2)에 저장된것은 지워지지 않는다.
  4. 다시 같은 프로그램을 실행한다.
  5. 이번에는 (1)로 부터 프로그램을 불러들이는 것이 아니라 (2)로부터 프로그램을 불러들인다. (3)의 입장에서 같은 프로그램을 불러들이는 것이지만 처음에는 속도 가 느린 보조기억장치로부터 불러들인 것이다. 두 번째부터 반복해서 불러들이 는 경우는 속도가 빠른 캐시 메모리로부터 불러들이는 것임으로 속도 개선의 효과를 준다.

Clock (클럭)과 FSB

클럭이란 CPU 및 기타 장치들을 동작시키기 위하여 메인보드의 클럭 발생 장치 로부터 만들어지는 일정한 주기로 진동하는 전기적인 리듬이다. MHz(메가헤르쯔)로 표시한다.

1Hz란 1초에 1주기를 진동하는 클럭이며 CPU는 기본적으로 1번의 클럭에 1개 명령 처리를 하고 있다.

CPU 및 시스템의 속도를 표시하는 단위로 사용된다.

FSB(Front Side Bus)는 메인보드의 클럭 발생장치에서 만들어져서 각 장치로 공급되는 클럭을 부르는 또 다른 이름이며 외부 클럭이라고도 한다. CPU 및 컴퓨터 내의 장치들은 클럭 발생 장치로부터 공급되는 클럭 속도에 따라 동작을 한다. 그러나 CPU는 이렇게 공급된 클럭을 그대로 이용하지 않고 “클럭 더블링”을 이용하여 여러 배로 그 속도를 증가시켜 사용한다.

데이터 처리용량에 따른 CPU의 종류

  • 동시 처리 가능한 데이터의 처리 용량에 따른 분류
  • 데이터를 전달하는 통로인 버스의 폭
  • 8bit는 컴퓨터가 처리하는 데이터 최소단위
  • 8088(8bit) => 80286(16bit) => 80386(32bit) => Pentium(64bit)로 발전

주기억 장치(Memory)

ROM/ROM BIOS 개요

ROM(Read Only Memory)는 읽기 전용의 기억소자로서 컴퓨터에서는 BIOS를 담기 위한 용도로 사용된다.
Basic Input/Output System로 컴퓨터 운영을 위한 기초 프로그램이다.
컴퓨터의 각 장치에 대한 기본 정보를 가지고 있으며 각 장치를 진단한다.
전원이 켜지면 컴퓨터를 기동시키고 자기 자신을 진단한다. BIOS는 절대 지워져서는 안 되며 그런 이유로 바이오스는 비휘발성 메모리인 ROM에 담아둔다.

RAM

RAM(Random Access Memory)은 RWM(Read Write Memory)라고도 하며 컴퓨터의 전원이 꺼지면 내부에 저장되어 있던 정보가 모두 사라지기 때문에 휘발성(Volatile) 메모리라고 한다. 램은 데이터를 읽고 쓰는 것이 자유로운 기억장치이며, 휘발성을 가지기 때문에 전원 공급이 끊어지면 메모리의 모든 내용은 지워진다.

DRAM의 데이터 저장 원리
DRAM(Dynamic RAM)의 데이터 저장 원리는 콘덴서가 전기를 저장하는 원리를 이용한다. 컴퓨터에서 데이터라고 하는 것은 실제로는 전기적인 신호의 흐름이다. 컴퓨터의 데이터는 1과 0으로 표현되고 이들은 각각 전기와 흐르는 상태와 흐르 지 않는 상태를 의미한다. 이런 전기적인 상태를 유지할 수 있다면 그것이 곧 저 장이다. 전기를 저장하는 매체 중 가장 흔한 것은 콘덴서 또는 배터리라고 불리 는 전자부품이다.
예를 들어 10101010이란 데이터를 저장하기 위해서 8개의 콘덴서를 준비하고 데 이터에 따라 1은 충전, 0은 충전안함, 형태로 저장을 한다면 이는 곧 10101010이 란 데이터의 저장한 것이다. 바로 이런 콘덴서의 원리를 이용하여 데이터를 저장 하는 장치가 DRAM이다.
그런데 콘덴서(배터리)에 한번 저장된 전기는 영원한 것이 아니라 사용하지 않아 도 자연 방전이 일어나고 이로 인해 일정시간이 흐르면 데이터를 상실하게 된다. 그래서 램은 데이터가 손실되기 전에 현재의 상태를 유지하기 위한 리플래시(재충전)작업을 하게 된다. 컴퓨터를 끄면 램이 이런 리플래시를 할 수 없기 때문에 데이터를 상실하는 덕이다. 즉, 휘발성의 성질을 가지는 것이다.DRAM은 원리가 단순하고 제조가 쉬워서 오래 전부터 컴퓨터의 주기억장치용 소자로 사용되어 왔으나 리플래시로 인한 대기시간의 증가로 현재는 새로운 형태 로 개량되고 있다.

램의 종류

구분 DRAM SRAM
리플래시 필요 불필요
액세스 속도 느리다 빠르다
회로구조 단순 복잡
집적도 높다 낮다
가격 싸다 비싸다
용도 주메모리용 캐시메모리용
DRAM과 SRAM의 비교

DRAM의 종류

SDRAM
SDRAM은 클럭 속도가 마이크로프로세서와 동기화되어 있는 DRAM을 의미한다. 클럭속도의 동기화는 주어진 시간 내에 프로세서가 수행할 수 있는 명령어 개수를 증가시키는데 도움을 준다.

DDR SDRAM
DDR(Double Data Rate) 메모리 SDRAM은 이전의 SDRAM에 비해 두 배의 데 이터를 주고받을 수 있는 메모리에 붙여진 이름이다. DDR 메모리는 PC2100과 PC1600 두개의 규격이 있는데 실제로 각각 2100MHz와 1600MHz로 동작하는 것 은 아니고, 100MHz 메모리 버스에서 동작하는 DDR SDRAM의 경우 PC200, 133MHz 버스에서 동작하는 경우 PC266 정도의 속도를 가진다.

DDR2 SDRAM
DDR SDRAM의 동작 속도를 2배 향상 시킨 DRAM

Rambus DRAM
미국 램버스사가 개발한 데이터전송 버스 Rambus 채널로 접속된 DRAM이다. 이 채널은 9비트의 버스를 이용하고 클럭 250MHz에 동기 해 데이터를 전송한다.

6.2 - SVG 이란?

개요

웹에서 자주 사용되는 SVG 이미지 형식에 대해 설명한다.

  • SVG은 Scalable Vector Graphics의 약어이다.
  • HTML을 표준화하고 있는 W3C가 채택하고 있다.
  • 내용은 XML 기반 텍스트 파일이다.
  • GIF , PNG , JPEG 가 비트맵 형식이 것에 비해, SVG는 좌표 정보에 의한 벡터 형식의 데이터이다.
  • 극도로 확대하거나 Retina 등의 고해상도 디스플레이로 표시해도 비트맵 데이터에 보이는 듯한 픽셀이 눈에 띄지 않는다.
  • <img> 태그로 표시하는 것 외에, HTML 파일내에 직접 기술하는 것도 가능하다.
  • 해상도에 맞추어, 스마트폰용, 고해상도용의 화상 파일을 각각 준비할 필요는 없다.
  • 직선이나 곡선을 조합하여 묘화하는 화상을 향하고 있다. 사진 데이터에는 적합하지 않는다.
  • 투과나 애니메이션에도 사용 가능하다.
  • 기본적으로는 텍스트 데이터이지만, gzip 로 압축한 것도 이용 가능하다.
  • 확장자는 *.svg이고, gzip 압축한 것은 *.svgz이다.
  • MIME 타입은 image/svg+xml 이다.
  • JavaScript와 조합하는 것도 가능하다.
  • XML을 손으로 입력하는 것은 쉽지 않기 때문에 Illustrator 등의 드로우 소프트웨어로 그려 SVG 파일에 출력하는 경우가 많다.
  • 2001년에 W3C가 SVG 1.0을 권고하였고,2003년에 SVG 1.1, 2011년에 SVG 1.1 2nd Edition을 권고하였다.
  • 처음에는 Microsoft는 VML, Adobe는 PGML을 권장하였지만, 업계 표준으로 SVG에 정착되었다.
  • Chrome 1.0, Firefox 1.5, IE9, Edge 12, Opera 8, Safari 3 이상에서 사용할 수 있다.

이 페이지에서는 SVG의 일부 기능만을 설명하므로 자세한 내용은 아래 사양 및 기타 참조를 하길 바란다.

사양서

SVG 쓰기 방법

이미지 파일로 쓰는 방법

SVG는 일반 이미지 파일로 <img>, background-image 등으로 읽을 수 있다.

svg-sample.svg

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="0" y="0" width="100" height="60" fill="#ddd" />
  <polygon points="50 10, 70 30, 50 50, 30 30" fill="#99f" />
</svg>

SVG

HTML에 아래와 같이 하면 표시할 수 있다.

<img src="/images/svg/svg-sample.svg" width="100" height="60">    // 압축되지 않은 경우

SVGZ

혹은, 상기의 *.svg 파일을 gzip 압축해, 확장자를 *.svgz로 변경한 것을 읽어들일 수도 있다.

<img src="/images/svg/svg-sample.svgz" width="100" height="60">   // gzip 압축의 경우

표시

태그로 쓰는 방법

아래와 같이 HTML 안에 직접 장성할 수도 있다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SVG Test</title>
</head>
<body>
<svg x=0 y=0 width=100 height=60 style="background-color: #ddd">
  <polygon points="50 10, 70 30, 50 50, 30 30" fill="#99f" />
</svg>
</body>
</html>

Drawing

직선, 사각형, 다각형, 원, 타원, 경로, 애니메이션, 링크를 그리는 방법에 대해서 알아보자.

직선 line

직선은 아래와 같이 그린다.

<line x1=y1=x2=y2=...>

x1(시작점의 X 좌표), y1(시작점의 Y 좌표), x2(종료점의 X 좌표), y2(종료점의 Y 좌표) 등을 지정한다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
  <line x1="5" y1="20" x2="100" y2="20" stroke="black" stroke-width="2"></line>
</svg>

표시

사각형 - Rect

사격형은 아래와 같이 그린다.

<rect x= y= width= height=...>

x(왼쪽 위의 X), y(왼쪽 위의 Y), width(가로 폭), height(높이) 등을 지정한다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
  <rect x="5" y="5" width="30" height="30" stroke="black" fill="#fff" stroke-width="2" />
</svg>

표시

다각형 - Polygon

다격형은 아래와 같이 그린다.

<polygon points=...>

posts 에는 x1 y1, x2 y2, x3 y3, … 와 같이 궤적 점을 지정합니다. 궤적의 끝은 시작점을 향해 닫힌다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
   <polygon points="5 20, 20 5, 35 20, 20 35" stroke="black" fill="#fff" stroke-width="2" />
</svg>

표시

원 - Circle

원은 아래와 같이 그린다.

<circle cx= cy= r=...>

cx(중심점의 X), cy(중심점의 Y), r(반경) 등을 지정한다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
   <circle cx="20" cy="20" r="15" stroke="black" fill="#fff" stroke-width="2" />
</svg>

표시

타원 - Ellipse

타원은 아래와 같이 그린다.

<ellipse cx=cy=rx=ry=...>

cx(중심점의 X), cy(중심점의 Y), rx(X축 방향의 반경), ry(Y축 방향의 반경) 등을 지정한다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
   <ellipse cx="20" cy="20" rx="15" ry="8" stroke="black" fill="#fff" stroke-width="2" />
</svg>

표시

경로 - Path

경로는 아래와 같이 그린다.

<path d=...>

d 에는, 패스 묘화의 명령을 기술합니다. M 5 20 은 x=5, y=20 으로 이동하라(Move to), L 20 5 는 x=20 y=5 에 선을 그려(Line to)를 의미한다.

  • Move to
    • M ( x y )+ : x, y로 이동
  • Lineto
    • L ( x y )+ : x, y에 선 그리기
  • Horizontal lineto
    • H ( x )+ : 수평 방향으로 선 그리기
  • Vertical lineto
    • V ( y )+ : 수직으로 선을 그립니다
  • Shorhand/smooth curveto
    • S ( x1 y1 x y )+ : 제어점(x1, y1), 종점(x, y)으로 하는 2차 베지어 곡선
  • Curveto
    • C ( x1 y1 x2 y2 x y )+ : 제어점 1(x1, y1), 제어점 2(x2, y2), 종점(x, y)으로 하는 3차 베지어 곡선
  • Closepath
    • Z : 경로 닫기

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background: #ddd">
   <path d="M 5 20 L 20 5 L 35 20 L 20 20" stroke="black" fill="transparent" stroke-width="2" />
</svg>

표시

2차 베지어 곡선
(Start) (x, y) (x1, y1)

3차 베지어 곡선
(Start) (x, y) (x1, y1) (x2, y2)

애니메이션 animate

애니메이션을 수행하는 방법은 아래와 같다.

<animate...>

attributeName으로 지정된 속성을 from에서 to 값까지 dur로 지정된 시간으로 변경한다. repeatCount는 횟수를 지정한다.

SVG

<svg x="0px" y="0px" width="400px" height="40px" style="background-color:#ddd">
  <rect x="5" y="5" width="30" height="30" stroke="black" fill="#fff" stroke-width="2">
    <animate attributeName="x" from="-30" to="400" dur="4s" repeatCount="indefinite" />
  </rect>
</svg>

표시

링크는 아래와 같이 설정한다.

<a xlink:href="...">

HTML의 <a>와 마찬가지로 클릭하면 URL로 이동한다.

SVG

<svg x="0px" y="0px" width="400px" height="60px" style="background-color:#ddd">
  <a xlink:href="https://www.devkuma.com">
    <polygon id="logomark-polyline" fill-rule="evenodd" clip-rule="evenodd"
      fill="#99f" points="200 10, 220 30, 200 50, 180 30"/>
  </a>
</svg>

표시

6.3 - AWS

EC2 (Elastic Compute Cloud)

  • Amazon의 대표적인 서비스이다.
  • EC2란 독립된 컴퓨터를 사용자에게 임대해주는 서비스이다.
  • 이 서비스를 통해 원하는 만큼 가상 서버를 구축하고 보안 및 네트워크 구성과 스토리지 관리가 가능하다.
  • 필요할 때마다 on/off가 가능하고 사용한 시간에 대해서만 비용을 지불하면 된다.

EC2의 가격정책

  • On-Demand : 실행하는 인스턴스에 따라 시간 또는 초당 컴퓨팅 파워로 측정 된 가격을 지불
    • 약정x , 한번 써보고 싶거나 유연하게 ec2를 사용하고 싶을 때 사용
  • Spot Instance : 경매 형식으로 시장에 남는 인스턴스를 저렴하게 구매해서 쓰는 방식
    • 최대 90%정도 저렴, 하지만 언제 다시 내주어야 할 지 모름… 시작 종료가 자유롭거나 추가적인 컴퓨팅 파워가 필요한 경우에 사용
  • Reserved Instance(RI) : 미리 일정 기간 (1~3년) 약정해서 쓰는 방식 (saving plan)
    • 최대 75%정도 저렴, 수요 예측이 확실할 때, 비용 절감을 위해 어느정도 기간의 약정이 가능한 사람들이 사용

      보통 On-Demand, Spot Instance를 사용

EC2 타입 종류

  • 범용: 모든 리소스의 균형을 알맞게 유지하여 사용하는 유형.
    • t2 : 저렴한 범용. 웹서버, DB.
    • m2 : 범용. 어플리케이션 서버.
  • 컴퓨팅 최적화: 고성능 프로세스를 활용하는 유형.
    • c5 : 컴퓨팅 최적화. CPU 성능이 중요한 어플리케이션/DB.
    • F1 : 하드웨어 가속. 유전 연구, 금융 분석, 빅데이터 분석.
  • 메모리 최적화: 대규모 데이터를 처리하는 유형.
    • r4 : 메모리 최적화. 메모리 성능이 중요한 어플리케이션/DB.
    • x1e : 메모리 최적화. Spark.
    • p3 : 그래픽 최적화. 머신러닝, 비트코인.
  • 저장 최적화: 높은 디스크 처리하는 유형.
    • h1 : 디스크쓰루풋 최적화 . 하둡/맵리듀스.
    • i3 : 디스크 속도 최적화. NoSQL/데이터 웨어하우스.
    • d2 : 디스트 최적화. 파일서버/데이터 웨어하우스/하둡.

EBS (Elastic Block Store)

  • EBS는 EC2 인스턴스에 사용할 영구 블록 스토리지 볼륨을 제공한다.
  • 쉽게 생각하면 EBS는 하드디스크라고 생각하면 되는데, AWS에서 실행중인 인스턴스에 디스크 공간이 필요할때 EBS를 사용하면 된다.
  • 필요한 용량에 맞게 구입이 가능하고 사용자가 지우기전까지 영구적으로 보존이 가능하다.
  • 내부적으로 데이터를 실시간 복제하고 있기 때문에 하드디스크에 비해 데이터를 잃어버릴 확률이 현저히 낮다고 한다.
  • 사용방법은 인터넷에 상세히 나와있지만 간단하게 설명하면 EBS는 USB처럼 EC2에 연결하여 사용이 가능하다.

AMI (Amazon Machine Image)

  • 인스턴스 생성에 필요한 모든 소프트웨어 정보를 담고 있는 템플릿 이미지라고 생각하면 된다.
  • 즉, OS, 어플리케이션, 서버 프로그램 설정 등이 미리 구성된 이미지다.
  • EC2 인스턴스를 시작할 때 AMI를 사용하여 OS 설치나 서버 소프트웨어 설정을 별도로 해주지 않아도 된다.

AMI는 총 3가지 유형

  • AWS AMI : AWS에서 제공하는 AMI이며 인스턴스를 시작할 때 AMI 설정하는 곳이 있는데 그게 AWS에서 기본으로 제공하는 AMI다.
  • AWS MarketPlace : 소프트웨어 회사가 AMI를 만들어서 판매하는 방식이다. 회사에서 특정 소프트웨어를 사용하는 경우에는 이 유형을 사용한다.
  • AWS Custom AMI : 사용자가 직접 AMI를 만들어서 서버를 런칭할 때 그 AMI를 써서 런칭한다.

ex) 실제 운영중인 EC2 인스턴스를 커스텀 AMI로 만들어서 동일한 환경으로 구성된 ec2를 빠르게 시작할 수 있다.

ELB (Elastic Load Balancer)

  • ELB는 둘 이상의 가용 영역에서 EC2 인스턴스, 컨테이너, IP주소 등 여러 대상에 걸쳐 수신되는 트래픽을 자동으로 분산시켜준다.
  • 즉, 부하를 적절하게 분배해주는 장치이고 서버가 죽지 않도록 알아서 관리를 해주고 인스턴스 상태를 자동 감지해서 오류가 있는 인스턴스는 분배 대상에서 제외 된다.

ElP (Elastic IP)

  • EC2 인스턴스 서버는 고정 IP가 아니다.
  • 인스턴스를 실행시키면 Public IP 주소를 받게 된다. 하지만 인스턴스가 중지가 되거나 사용하지 않은 상태로 변경이 되면 IP주소는 사라지게 된다. 다시 실행시키면 새로운 IP를 받게 된다.

매번 실행시 새로운 IP주소를 받게되는 이유는 사용할 수 있는 IP주소가 한정적이기 때문이다. 약 40억개의 IP주소를 사용할 수 있는데, 40억대의 사용자만 인터넷을 할 수 있는 것이다. 그래서 IP를 돌려막기? 개념으로 매번 새롭게 IP를 부여해주는 것이다.

매번 새로운 IP주소를 받으면 서비스가 어려우니 이를 해결하기 위해 Elastic IP를 사용한다. Elastic IP는 고정 IP주소를 할당하게 해준다. 사용하지 않은 상태여도 IP는 고정되어있다. 하지만 EC2 인스턴스에 연결하여 사용하지 않은 상태이면 요금이 부과된다.그 이유는 Elastic IP를 할당 받기만 해놓고 사용하지 않은 상태이면 다른 사람들이 사용할 수 있는 기회가 적어지기 때문에 요금을 부과한다고 한다.

Auto Scaling

Auto Scaling이란 시스템을 자동으로 늘리고 줄여주는 서비스이다.

예를들면 서비스에 사용자가 몰리게 되면  참여하고 있던 서버의 CPU 사용률이 점점 높아진다. 그러다가 CPU 점유율이 80%를 넘게되면 미리 준비된 이미지(AMI)를 이용해서 인스턴스를 생성하고, ELB에 연결해서 트래픽을 새로 생성한 EC2 인스턴스에 분산한다.

트래픽이 점점 줄어들면서 CPU 사용률이 20% 아래로 떨어지면 EC2 인스턴스가 순차적으로 제거된다.

VPC (Virtual Private Cloud)

  • VPC는 사용자 AWS 계정 전용 가상 네트워크이다. (네트워크 망)
  • AWS와 같은 클라우드 서비스에선 수많은 인스턴스들이 물리적으로 동일한 네트워크나 장비에서 돌아가게 되는데, 이를 논리적으로 완전히 분리 시켜 준다.
  • VPC별로 네트워크를 구성할 수 있고 각각 VPC에 따라 네트워크를 다르게 설정해 줄 수 있다.

VPN (Virtual Private Network)

  • 큰 규모의 조직이 여러 곳에 분산되어 있는 컴퓨터들을 연결하는 보안성이 높은 사설 네트워크를 만들거나, 인터넷을 활용하여 원격지 간에 네트워크를 서로 연결하고 암호화 기술을 적용하여 보다 안정적이며, 보안성 높은 통신 서비스를 제공하는 서비스이다.

ex) 재택 근무하는 사람들이 안전한 네트워크 연결을 사용하여 사무실에 있는 네트워크, 파일 등을 인터넷을 통해 사무실에서 근무할 때와 똑같이 이용하기 위해 VPN을 사용한다.

IAM(Identity and Access Manager)

AWS의 모든 솔류션 서비스 및 자원에 대해 개별적으로 권한을 부여할 수 있는 권한 솔류션이다.

IAM

CloudlTrail

  • CloudlTrail은 AWS계정의 활동 기록이다.
  • AWS에서 누가 어떤 일을 했는지에 대한 내용이 기록된다.
  • CloudTrail을 사용하면 AWS 인프라에서 계정 활동과 관련된 작업을 기록하고 모니터링하며 보관까지 할 수 있고 로그 보관은 S3에 저장된다.

Cloud Watch

  • CloudWatch는 AWS 서비스 및 자원 활동에 초점을 맞추고, 그 상태와 성능에 대해 보고해 준다.
  • CloudWatch는 AWS 리소스와 어플리케이션의 모니터링 서비스.

Route53

  • 컴퓨터는 숫자로 된 IP로 통신을 한다. 그런데, ip주소를 기억하는건 쉽지 않으니 ip주소에 도메인 네임을 붙여 쉽게 기억할 수 있도록 하는것이 dns(Domain Name Service)인데, 아마존에서 DNS를 서비스화 한 것이 Route53이다.

route53의 핵심 기능은 도메인 네임 서버를 임대해준다. (도메인 서버 등록 대행자 역할과 네임 서버를 임대해주는 역할)

CloudFront

  • AWS에서 제공하는 CDN 서비스이다.

  • 캐쉬와 CDN(Content Delivery Network) 역할을 하며, 캐싱을 통해 사용자에게 좀 더 빠른 전송 속도를 제공함을 목적이다.

  • 전 세계에 배치된 Edge Location을 이용하여 효율적인 컨텐츠 배포 구조를 제공한다.

  • Edge Location은 cloud front를 위한 캐시 서버들의 모음이다. (전 세계 주요 도시에 캐시 서버를 구축)

  • Origin Server

    • 원본 데이터를 가지고 있는 서버이다.
      • 보통 AWS에서의 Origin Server는 S3, Ec2 instance이다.
  • Edge Server = Edge Location

    • AWS에서 실질적으로 제공하는 전 세계에 퍼져있는 서버이다.
    • Edge Server에는 요청받은 데이터에 대해서 같은 요청에 대해서 빠르게 응답해주기 위해 Cache 기능을 제공합니다.

CloudFront

  1. 사용자가 웹사이트에 접속하여 이미지 파일 및 HTML파일을 요청
  2. DNS 요청을 최대한 빠르게 해줄 수 있는 Edge Location에 라우팅을 함
  3. Edge Location에 해당 캐시에 요청된 파일이 있는지 확인
  4. 해당 캐시에 요청된 파일이 없으면 오리진 서버에 파일을 전달함
  5. 오리진 서버는 다시 Egde Location에 파일을 전달함 (해당 파일은 앞으로 캐시에 추가 됨)
  6. Edge Location은 사용자에게 파일을 전달함

Security Group

  • 인스턴스에 대한 인바운드 및 아웃바운드 트래픽을 제어하는 가상 방화벽 역할을 한다.
  • 이 서비스를 이용하면 재택하면서 DB에 붙을 수 있다.

참조