Android, Cocos2d, Java Web, Linux, reading...

UTC, GMT, KST란?


리눅스를 공부하다보면 꼭 시간을 다룰 일이 생긴다. 이 때 UTC인 경우가 있고, GMT인 경우가 있고, KST인 경우가 있다. 사실 UTC와 GMT는 그냥 단지 어떤 시간인데 한국 시간과 달라서 그냥 아무 생각없이 시간만 맞으면 되도록 블로그들에 나와있는대로 설정만 하다가 갑자기 궁금해서 알아보기로 했다.

  • UTC

    협정 세계시(프랑스어 : Temps Universel Coordonné, 영어 : Coordinated Universal Time)라고 불리며 국제원자시와 윤초 보정을 기반으로 표준화되었고 1972년 1월 1일부터 시행된 국제 표준시이다. 프랑스어나 영어나 둘 다 약자는 UTC가 아닌데 협정 세계시를 UTC로 한 이유는 영어권의 사람들은 영어로 된 약자인 CUT을, 프랑스어권의 사람들은 프랑스어로 된 약자인 TUC를 사용하길 원해 분쟁이 발생했다. 그래서 결국 두 언어 모두 C, T, U로 구성되어 있다는 것에 착안해 UTC로 정했다고 한다.

  • GMT

    그리니치 평균시(Greenwich Mean Time)의 약자로 런던을 기점으로 하고, 웰링턴에 종점으로 설정되는 협정 세계시의 시간대이다. 이전에는 협정 세계시로 GMT를 사용했으나 1972년 1월 1일부터 협정 세계시(UTC)를 공식 표현으로 사용한다. 하지만 아직도 영국 BBC 방송을 중심으로 GMT란 표현은 널리 쓰이고 있고 UTC와 초의 소숫점 단위 정도의 오차만 있기 때문에 GMT와 UTC는 거의 같다고 보면 된다.

    참고 : 런던을 기점으로 한다고 해서 런던과 시간이 같은지 궁금했다. 그래서 직접 비교해봤는데

    GMT와 BST(British Summer Time, 영국시간)은 한 시간 정도 차이가 난다. 왜 KST처럼 S가 Standard가 아니라 Summer이고 런던을 기점으로 했는데 왜 다른지 궁금해서 조금 더 찾아보니 영국의 겨울철에만 GMT와 같고 여름철에는 GMT + 1이라고 한다. 그래서 이를 BST, 즉, British Summer Time이라고 명명한 것이다.

  • KST

    한국 표준 시간(Korean Standard Time)의 약자로 말 그대로 한국 시간을 의미한다. 원래는 UTC(또는 GMT) + 08:30으로 했으나 UTC(또는 GMT) + 09:00으로 바꿨다고 한다. 자세한 내용은 밑의 사이트를 참고해주길 바란다. 즉, 한국 시간은 UTC(또는 GMT) + 9를 해주면 된다. 예를 들어, UTC(또는 GMT)가 2018-07-25 06:21:35이면 KST는 2018-07-25 15:21:35이다.




참고 블로그 :

  • https://ko.wikipedia.org/wiki/%ED%98%91%EC%A0%95_%EC%84%B8%EA%B3%84%EC%8B%9C
  • https://ko.wikipedia.org/wiki/%EA%B7%B8%EB%A6%AC%EB%8B%88%EC%B9%98_%ED%8F%89%EA%B7%A0%EC%8B%9C
  • https://ko.wikipedia.org/wiki/%ED%95%9C%EA%B5%AD_%ED%91%9C%EC%A4%80%EC%8B%9C
  • https://greenwichmeantime.com/

阅读全文 »


iSCSI initiator 설정


저번 포스팅에서 iSCSI Target을 설치했는데, 이번 포스팅에서는 iSCSI initiator를 설치해볼 것이다. 저번 포스팅에서도 언급했지만 iSCSI initiator 환경은 VM의 CentOS 7이다.

이따가 iSCSI Target의 디스크가 연결됐을 때와 비교하기 위해서 현재 iSCSI initiator의 디스크 현황을 보면

원래 있던 디스크에서 추후에 LVM으로 묶기 위해 4G, 6G (가상)디스크를 추가해 준 상태이다.

먼저 update를 해준다.

yum update -y

update를 마쳤으면 이제 iSCSI 클라이언트, 즉, initiator을 설치한다.

yum install iscsi-initiator-utils -y

(참고 : Ubuntu는 apt-get install open-iscsi)

다 설치했으면 저번 포스팅에서 iSCSI Target 장비에 인증 기능을 활성화했기 때문에(Target에다가 계정 및 IP대역 설정) 해당 Target에 접근하기 위해서는 iSCSI initiator에 설정해 준 계정을 등록해야 한다.

vim /etc/iscsi/iscsid.conf

빨간색으로 된 부분을 추가해주면 되는데 저번 포스팅에서 Target에다가 username은 pooh, 비밀번호는 pooh1234로 설정했기 때문에 저렇게 입력한 것이다. node는 실제 iSCSI Target에 username과 비밀번호를 이용하여 인증하기 위한 설정이고 discovery 부분은 discovery 단계에서의 인증 정보를 의미한다.

다 설정해줬으면 이제 iSCSI Target 시스템을 검색해보자. Target에 접근하려면 당연히 Target의 IP를 알고 있어야 한다. 만약 이를 잊어버리거나 모른다고 할 때 Target에서 해당 initiator의 IP가 접근할 수 있도록 허용해줬다면 다음 명령어로 Target의 IP를 알아낼 수 있다.

iscsiadm -m node

이렇게 iSCSI Target의 IP와 함께 저번 포스팅에서 지정해준 Target의 이름이 나온다. 만약 IP를 알고 있다면 이렇게도 명령어를 사용할 수 있다.

iscsiadm -m discovery –type sendtargets –portal 192.168.0.92

둘 다 결과값이 똑같다. 둘 중 편한 명령어를 사용하면 된다.

그럼 만약 Target이 접근을 허용하지 않은 IP가 저렇게 명령어를 입력하면 어떻게 될까?? 다음 그림처럼 된다.

이런 식으로 나오게 된다. 아예 없다고 나온다.

이제 iSCSI Target 시스템에 로그인을 할 차례이다. Target의 IP와 이름을 알았으니 이렇게 써주면 된다.

iscsiadm -mode node –targetname iqn-2018-07.pooh:storage.lun1 –portal 192.168.0.92 –login

(참고 : –mode 대신 –m, -m을 써도 되고 로그아웃을 하려면 맨 뒤에만 –login 대신 –logout으로 바꿔주면 된다.)

밑에 successful이 보인다. 로그인에 성공한 것이다.

만약에 Target이 허용하지 않은 IP가 똑같이 로그인을 하면

이렇게 Could not login이라고 뜬다.

이제 iSCSI를 통해서 iSCSI Target에 있는 5G 디스크를 사용할 수 있게 되었다. 이를 확인하기 위해 이전 디스크 현황과 비교해보면

맨 밑에 5G 디스크가 추가되었음을 확인할 수 있는데 이게 바로 iSCSI Target에 있는 그 5G 디스크이다. 즉, iSCSI로 연결된 것이다.

다음 명령어로도 확인이 가능하다.

cat /proc/scsi/scsi

빨간 부분을 보게되면 Lun 1번의 VIRTUAL-DISK 즉, iSCSI로 연결된 디스크를 의미한다.

이제 이 iSCSI로 연결된 디스크를 사용하려면 똑같이 fdisk로 파티션 지정해주고 mkfs로 파일시스템을 생성한 다음 마운트 시켜주고 fstab으로 컴퓨터가 부팅될 때마다 마운트 된 파일시스템이 적용될 수 있도록 설정을 해주면 된다. 하지만 최종 목표는 이를 initiator의 디스크들과 함께 LVM으로 묶어서 사용하는 것이기 때문에 지금 이 과정들을 하지는 않겠다. 다음 포스팅에서는 initiator의 디스크들과 iSCSI로 연결된 디스크를 LVM으로 묶어서 파일시스템으로 만들어 마운트까지 시켜볼 것이다.


참고 블로그 :

  • https://m.blog.naver.com/PostView.nhn?blogId=jesstter&logNo=220767176214&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

阅读全文 »


iSCSI Target 설정


저번 포스팅에서 iSCSI에 대해서 알아보았다. 이 iSCSI와 이전에 배웠던 LVM을 통합해서 어떤 한 노드에서 iSCSI를 통해 다른 노드에 있는 디스크를 자신의 디스크처럼 사용하고 이를 원래 있던 디스크들과 함께 LVM으로 묶어볼 것이다. 이해를 돕기 위해 그림을 그려보면

두 노드가 있는데, 하나의 노드는 iSCSI target이고 하나의 노드는 이 iSCSI target에 접근하는 iSCSI initiator이다. 원래 iSCSI initiator에는 SSD1, SSD2만 있지만 iSCSI target의 SSD4를 iSCSI를 통해 자신의 디스크처럼 사용한다는 뜻이다. 결국 iSCSI initiator에는 SSD1, SSD2, SSD4가 있는 상태인 것이고 이를 LVM으로 묶어본다는 말이다. 이제 이를 실제로 구현해보자. 환경은 VM에서 진행하였고 iSCSI initiator은 CentOS 7, iSCSI target은 Ubuntu 16.04이다.

먼저 update를 해준다.

sudo apt-get update -y

update를 마쳤으면 이제 iSCSI 서버, 즉, target을 설치한다.

sudo apt-get install tgt -y

(참고 : CentOS는 yum install scsi-target-utils)

다 설치했으면 iSCSI 서버를 실행한다.

서버를 실행하고 나면 iSCSI target이 될 디스크 즉, 위 그림의 SSD4에 해당하는 디스크의 이름을 먼저 지정해준다.

sudo tgtadm –lld iscsi –op new –mode target –tid 1 -T iqn-2018-07.pooh:storage.lun1

(참고 : 해당 target 삭제는 sudo tgtadm –lld iscsi –op delete –mode target –tid 1)

–tid 1은 밑에 보면 Target 1 : iqn-2018-07.pooh:storage.lun1의 Target 1을 의미한다. –tid 3이라고 지정하면 Target 3으로 지정이 된다. 그 뒤에 iqn-2018-07.pooh:storage.lun1이 이름인데 이에 대해 설명하면 iqn은 iSCSI qulified name의 약자로 target의 디스크가 유일한 이름을 가지도록 해주는 iSCSI 표준이며, initiator가 해당 장치를 찾기 위한 도메인이름이라고 생각하면 된다.

iqn.yyyy-mm.~[:identifier]

형식은 이러하며 iqn 뒤에 ~부분이 도메인, 뒤의 identifier는 디스크(볼륨) 이름이다. 하지만 이는 알아보기 위해서 이렇게 형식을 지정해준 것일 뿐 사실 iqn~ 이럴 필요 없이 aaa 이렇게 이름을 지어도 전혀 상관은 없다. 필자의 경우 2018년 7월에 만들었고 도메인 이름을 그냥 pooh라고 했으며 identifier부분은 저장소 lun(logical unit number)1이라는 뜻에서 저렇게 storage.lun1이라고 붙여준 것이다.

그 밑을 보게되면 sudo tgtadm –lld iscsi –op show –mode target (또는 sudo tgt-admin -s) 명령어를 통해 iSCSI 서버의 데이터들을 확인할 수 있는데

Target 1의 이름이 지정되어 있고 Driver는 iscsi이며 따로 볼륨을 지정하지 않고 이름만 지정을 했는데 LUN 0이 있음을 확인할 수 있다. 이는 controller에서 사용하는 것이기 때문에 있는 것이고 Size는 0MB라고는 나와있지만 옆에 Block size: 1이므로 없는 것이 아니다. 그래서, LUN을 지정할 때 1번부터 지정하는 것이다.

LUN이란 Logical Unit Number라는 뜻으로 해석하면 논리 단위 번호라는 의미이다. 현 상황에 빗대어 말하면, 호스트의 SCSI LUN 번호로 제공되는 주소 지정 방식을 통해 외부에 노출되는데 대상 ID(여기서는 SCSI ID)와 결합되어 포트의 디스크를 고유하게 식별하는 번호이다.

현재 iSCSI 서버(target)의 디스크 현황은 이러하다. 원래 있던 40G의 디스크에다가 iSCSI target 디스크를 지정해주기 위해 5G, 7G (가상)디스크를 추가했다.
(VM에서 (가상)디스크를 추가하는 방법이 궁금하시면 ‘LVM 실습(1) - 파티선 설정’ 편을 참고해주세요!)

sudo fdisk -l

우리는 빨간색으로 표시된 5G 하드디스크(/dev/sdb)를 iSCSI target으로 지정해서 iSCSI initiator가 이를 로컬디스크처럼 사용할 수 있도록 할 것이다. 아까 봤던 구성도에서 SSD4에 해당한다.

이제 iSCSI target이 될 디스크를 등록해주자.

sudo tgtadm –lld iscsi –op new –mode logicalunit –tid 1 –lun 1 -b /dev/sdb

이를 해석하면 Target 1에 5G 하드디스크(/dev/sdb)를 LUN 1번으로 등록할 것이라는 의미이다.

잘 등록됐는지 확인해보면 /dev/sdb가 있고 크기도 5G로 되어있다. 그 밑 부분은 이 Target 1으로 접근할 때 허용하는 계정 부분과 IP 대역 부분인데 아직 바인딩(포트 오픈)을 안 해줬기 때문에 빈 칸인 것이다. 먼저 계정부터 설정해보자.

sudo tgtadm –lld iscsi –op new –mode account –user pooh –password pooh1234

user는 pooh 비번은 pooh1234인 계정을 설정해주었다.

sudo tgtadm –lld iscsi –op bind –mode account –tid 1 –user pooh

해당 설정을 Target 1에 적용한다는 의미이다. 따라서, iSCSI initiator가 Target 1에 접근할 때 해당 계정이 있어야만 접속할 수 있다. 모든 IP 대역을 허용한다고 할 때 계정을 설정해주지 않으면 누구나 다 접속할 수 있기 때문에 계정을 설정해주는 것이 좋다.

설정이 잘 되었는지 확인해보면

sudo tgtadm –lld iscsi –op show –mode target 또는 sudo tgt-admin -s

아까와는 다르게 맨 밑을 보면 Account information 부분에 pooh라고 되어있음을 확인할 수 있다. 그 다음은 해당 IP대역을 설정해주자. 필자는 특정 IP만 접근 가능하도록 설정할 것이다.

sudo tgtadm –lld iscsi –op bind –mode target –tid 1 -I 192.168.0.9

이는 iSCSI initiator가 Target 1에 접근할 때 해당 IP(192.168.0.9)만 접속할 수 있다는 것을 의미하고 해당 설정을 Target 1에 적용한다는 뜻이다. 모든 IP가 접속 가능하게 하려면 해당 IP부분에 ALL이라고 적어주면 된다.

(참고 : 설정해준 IP를 제거하려면 sudo tgtadm –lld iscsi –op unbind –mode target –tid 1 -I 192.168.0.9 )

다른 부분은 다 똑같으니 패스하고 맨 밑에 ACL information 부분에 해당 IP가 추가됐음을 확인할 수 있다.

잘 bind되었는지 확인해보면

sudo netstat -nap grep tgtd

이제 마지막으로 여태까지 설정한 tgt 정보를 설정파일로 등록해준다.

tgt-admin –dump > /etc/tgt/targets.conf

이 명령어는 pooh계정에서 sudo로 해도 permission denied 걸려서 그냥 root계정으로 수행했다.

이렇게 해당 설정들이 들어가게 되는데 암호부분은 직접 입력해줘야 한다. 아까 pooh라는 user에 비번을 pooh1234로 해줬으므로 그대로 pooh1234로 바꿔주자.

이제 iSCSI target 설정이 끝났다. 다음 포스팅에서는 iSCSI initiator 설정을 해보자.


참고 블로그 :

  • https://m.blog.naver.com/PostView.nhn?blogId=jesstter&logNo=220767176214&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
  • https://www.joinc.co.kr/w/Site/System_management/iSCSI
  • http://kindno.tistory.com/entry/%EB%94%94%EC%8A%A4%ED%81%AC-%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80%EC%97%90%EC%84%9C-%EC%93%B0%EC%9D%B4%EB%8A%94-%EC%9A%A9%EC%96%B4%EC%9D%B8-LUN%EC%9D%B4%EB%9E%80
  • http://thinkfarm.tistory.com/entry/ISCSI-%EC%84%A4%EC%A0%95

阅读全文 »


unable to delete {IMAGE ID} (must be forced) - image is referenced in multiple repositories


지난 포스팅에서 dockerfile로 이미지를 작성하는 법에 대해서 알아봤는데 그러다보니 잘못 만들어진 이미지들도 많고 필요없어진 이미지들도 많다. 그래서 제거를 하려는데 밑에 보면 IMAGE ID가 같은 것이 있다(그 위에위에 같은 것이 또 있지만 신경쓰지 말아주세요). 이녀석부터 지워보자.

Docker Image를 지우는 명령어는 docker rmi <IMAGE ID>이다.

docker rmi dc69bffc5350

unable to delete 즉, 지울 수 없다는 메시지가 떴고 여러 저장소에서 이미지가 참조되고 있다고 나온다. 그래서 must be forced 반드시 강제되어야 한다고 나와있다. 따라서, -f 옵션을 줘서 강제로 삭제해주면 된다.

docker rmi -f dc69bffc5350

이미지가 잘 지워진다.

阅读全文 »


Dockerfile(2)


저번 포스팅에서 dockerfile에 대해서 알아보았고 dockerfile로 이미지까지 만들어보았다. 이번 포스팅에서는 만든 이미지를 컨테이너로 실행했을 때 해당 설정들이 잘 들어가있는지 확인해보자.

저번 포스팅에서 만든 dockerfile이다. 이를 poohpooh라는 이름과 test 태그로 이미지를 build 하였다. docker run 명령어로 컨테이너를 실행시킨다.

docker run -it poohpooh:test /bin/bash

해당 컨테이너로 접속하였다. 이제 각 설정들을 하나하나 확인해보자.

  • FROM ubuntu:16.04

    ubuntu:16.04를 기본 이미지로 했기 때문에 ubuntu:16.04가 깔려 있어야 한다. cat /etc/*release* 명령어로 확인해보면

    ubuntu:16.04가 잘 설치되었다.

  • MAINTAINER pooh

    dockerfile 만든 사람의 정보가 쓰여 있는 것으로 build 할 때 아무런 영향이 없으므로 넘어가자.

  • ADD linux-2.4.32.tar.bz2 /pooh

    호스트에 있는 linux-2.4.32.tar.bz2 파일을 컨테이너의 /pooh라는 곳에 추가하겠다는 의미이다. 저번 포스팅에도 언급했지만 경로가 따로 없고 파일명만 있는 것은 dockerfile과 같은 경로에 있기 때문이다. 그리고 ADD는 호스트의 압축 파일(tar.gz, tar.bz2, tar.xz)인 경우 압축을 해제하고 tar을 풀어서 컨테이너에 추가된다고 했다. 실제로 그렇게 되어있는지 /pooh로 가서 확인해보자.

    linux-2.4.32.tar.bz2가 있는 것이 아닌 linux-2.4.32라는 이름의 디렉토리가 있는 것을 확인할 수 있다. 해당 디렉토리로 가보면

    해당 리눅스 파일들이 있음을 확인할 수 있다. 즉, tar.bz2 파일이 ADD에 의해 압축이 해제되고 tar이 풀린 채로 컨테이너에 저장된 것이다.

  • WORKDIR /pooh

    RUN, CMD, ENTRYPOINT 등의 명령이 실행될 디렉터리로 밑의 RUN 명령어들을 /pooh에서 실행했다고 생각하면 된다. 그리고 docker run으로 컨테이너에 처음 접속할 때 경로를 보면 /pooh로 되어있음을 확인할 수 있는데

    이 역시 WORKDIR을 /pooh로 해줬기 때문이다.

  • COPY linux-copy.tar.bz2 /pooh

    ADD와 똑같이 호스트에 있는 linux-copy.tar.bz2 파일을 컨테이너의 /pooh라는 곳에 추가하겠다는 의미이다. 하지만 저번 포스팅에서 COPY는 호스트에 있는 압축파일을 추가할 때 압축을 해제하지 않는다고 했다. 실제로 확인을 해보면

    아까 ADD로 인해 추가된 linux-2.4.32.tar.bz2는 압축이 풀어지고 tar까지 풀어져서 linux-2.4.32라는 디렉토리로 되어있는 반면 linux-copy.tar.bz2는 압축이 풀어지지 않아 파일 형태 그대로 컨테이너에 있다.

  • RUN apt-get update -y, RUN apt-get install mysql-client -y

    이 RUN 명령어를 통해 해당 컨테이너에 mysql-client를 설치하였다. 잘 설치가 되어있는지 확인해보자.

    mysql에 root 계정으로 들어가는 것은 실패했다. 지금 난 에러는 mysql 서버가 실행되지 않아서 나는 에러인데 지금은 mysql 에러를 잡으려고 하는 것이 아니기 때문에 이 부분은 다루지 않겠다. 여기서는 mysql 명령어가 실행됐다는 것에 초점을 맞추자. 만약 mysql-client가 지 않았다면 mysql : command not found가 떠야 한다. 하지만 mysql -uroot -p 명령어가 실행은 됐기 때문에 RUN 명령어들도 잘 수행됐음을 알 수 있다.

  • VOLUME [“/pooh”]

    컨테이너의 /pooh 디렉토리를 Docker-Volume에 마운트시킨다는 의미이다. 이렇게 해주면 -v 옵션으로 따로 주지 않아도 Docker-Volume과 연동이 된다. 단, Docker-Volume의 이름은 해쉬값으로 저장한다. 이에 대한 자세한 내용은 저번 포스팅에서도 얘기했지만 추후에 자세하게 다룰 예정이다.

阅读全文 »


Dockerfile(1)


이전 포스팅에서는 만들어져 있는 이미지 파일을 다운받았다면 이번 포스팅에서는 직접 이미지를 만드는 방법에 대해서 알아보도록 하자. 이때 사용하는 것이 Dockerfile이다. Dockerfile은 Docker 이미지 설정파일로 Dockerfile에 설정된 내용대로 빌드해서 이미지를 생성하는 것이다. 실습 환경은 CentOS 7에서 진행하였다.

먼저 기본(베이스) 이미지를 지정해줘야 하는데 이는 반드시 지정해줘야 하며 어떤 이미지도 베이스 이미지가 될 수 있다. tag는 될 수 있으면 latest(기본값)보다 구체적인 버전(16.04등)을 지정하는 것이 좋은데, 그 이유는 latest는 최신 버전이다보니 처음에 셋팅했던 환경과 호환이 안 되는 상황이 벌어질 수 있기 때문이다. 이미 만들어져 있는 다양한 베이스 이미지는 Docker hub에서 확인할 수 있다.

다음은 필자가 만든 dockerfile 이미지인데 이를 바탕으로 각 명령어들에 대해 알아보자.

  • FROM: Docker 이미지는 기존에 만들어진 즉, 베이스 이미지를 기반으로 생성하기 때문에 베이스 이미지를 설정해줘야한다. 어떠한 이미지도 베이스 이미지가 될 수 있고 이 이미지들은 Docker hub에서 확인할 수 있다. <이미지 이름>:<태그> 형식으로 설정해주면 되고 태그를 따로 지정하지 않으면 latest를 default값으로 사용하며 이미지를 생성할때 FROM에 설정한 이미지가 로컬에 있으면 바로 사용하고, 없으면 Docker Hub에서 받아온다. 필자는 ubuntu:16.04를 베이스 이미지로 했다.

  • MAINTAINER: Dockerfile을 관리하는 사람의 이름 또는 이메일 정보를 적는 부분으로 빌드에 딱히 영향을 주지는 않으므로 적지 않아도 아무런 지장이 없다. 필자의 경우 그냥 뒤에 닉네임만 붙였다.

  • ADD : 해당 파일이나 디렉토리를 이미지로 복사한다. 파일뿐만 아니라 디렉터리도 설정할 수 있고, 디렉터리를 지정하면 디렉터리의 모든파일을 복사한다. 와일드 카드를 사용하여 특정 파일만 복사할 수 있다. dockerfile의 ADD와 COPY에 경로 없이 파일명만 있는 이유는 dockerfile의 경로와 같은 경로에 있기 때문이다. 사용법은

    ADD <복사할 호스트 파일 경로> <이미지에서 파일이 위치할 경로>

    <이미지에서 파일이 위치할 경로>는 무조건 절대경로로 지정해줘야 하는 반면, <복사할 호스트 파일 경로>는 dockerfile이 있는 경로보다 상위 경로는 사용할 수 없고 하위 경로라도 절대 경로로 지정할 수 없다. 하나의 예를 보자(위의 dockerfile과는 별개로 테스트용으로 만들어 본 것이니 헷갈리지 말아주세요).

    여기를 보게 되면 /home/pooh/pooh_test/poohpooh/linux-test.tar.bz2가 있음을 확인할 수 있다. 즉, 이 리눅스 소스파일은 dockerfile의 하위 경로에 있고 이를 절대경로로 ADD를 이용해 컨테이너에 넣어보려고 했다. 그래서 dockerfile을 다음과 같이 작성했다.

    이 상태에서 dockerfile이 있는 경로(/home/pooh/pooh_test)에서 dockerfile을 poohpooh라는 이름과 test라는 태그로 빌드하면

    docker build -t poohpooh:test .

분명 저 경로에 linux-test.tar.bz2 파일이 있음을 확인했는데도 불구하고 에러가 뜬다. 그럼 이를 상대경로로 나타내보자. /home/pooh/pooh_test/poohpooh/linux-test.tar.bz2를 현재 dockerfile이 있는 경로를 .으로 나타내서 ./poohpooh/linux-test.tar.bz2로 바꿔보자.

그러고 나서 다시 dockerfile을 poohpooh라는 이름과 test라는 태그로 빌드해보면

docker build -t poohpooh:test .

분명 같은 경로인데도 아까 절대경로로 지정해줬을 때와는 다르게 dockerfile이 잘 빌드되었다(이미지가 잘 생성되었다).

다시 돌아와서 ADD는 호스트 파일 경로 안에 압축 파일(tar.gz, tar.bz2, tar.xz)인 경우에는 압축을 해제하고 tar을 풀어서 추가되지만 인터넷 파일 URL은 압축만 해제한 뒤 tar 파일이 그대로 추가된다.

위의 그림을 보게 되면 현재 호스트 경로에 linux-2.4.32.tar.bz2 즉, 압축된 리눅스 소스파일이 있고 ADD를 이용해서 컨테이너에 넣어볼 것이다.

  • WORKDIR: RUN, CMD, ENTRYPOINT 등의 명령이 실행될 디렉터리이고, 중간에 다른 디렉토리로 변경이 가능하며 WORKDIR은 절대경로, 상대경로 둘 다 사용 가능하다. 사용법은

    WORKDIR <경로>

    dockerfile을 보게되면 WORKDIR /pooh로 되어있고 그 위에 RUN apt-get update -y, RUN apt-get install mysql-client -y가 있다. 저 2개의 RUN 명령어를 /pooh에서 실행한다는 뜻이다.

  • COPY : ADD와 거의 동일한데, 차이가 있다면 COPY는 압축파일을 추가할 때 압축을 해제하지 않고 파일 URL을 사용할 수 없다. ADD와 COPY의 차이를 보기 위해 리눅스 소스파일을 다운받은 후 이름을 바꿔서 컨테이너에 옮겨볼 것이다.

  • RUN: RUN <명령> 형식으로 셸 스크립트 구문을 사용할 수 있고 FROM 에서 설정한 이미지 위에 쉘 스크립트 혹은 명령을 실행하는 구문이다. RUN으로 실행한 결과가 새 이미지로 생성되고 실행내역을 이미지의 히스토리에 기록하지만 FROM으로 설정한 이미지에 포함된 /bin/sh 실행 파일을 사용하며 /bin/sh 실행파일이 없으면 사용할 수 없다. 대신 RUN ["<실행 파일="">", "<매개 변수1="">", "<매개 변수2="">"] 형식으로 사용하면 셸 없이 바로 실행하며 배열형태로 설정한다. RUN으로 실행한 결과는 캐시되며 다음 빌드때 재사용, 캐시된 결과를 사용하지 않으려면 docker build 명령에서 --no-cache 옵션을 사용한다. dockerfile의 RUN 부분을 보면 -y가 뒤에 붙어있는데 이는 이미지 생성 중에 입력을 받을 수 없기 때문에 yes 명령어인 -y 옵션을 준 것이다.

  • VOLUME : 디렉터리의 내용을 컨테이너에 저장하지 않고 호스트에 저장하고, 사용법은
    VOLUME <컨테이너 디렉터리> 또는 VOLUME [”<컨테이너 디렉터리1>”,”<컨테이너 디렉터리2>“]처럼 배열형식으로 지정이 가능하고 해당 볼륨을 호스트의 특정 볼륨과 연결하려면 docker run 명령에서 -v 옵션을 사용한다. -v 옵션은

    -v <호스트 디렉토리>:<컨테이너 디렉토리>

    추후에 Docker-Volume에 대해서 자세하게 포스팅 할 것이기 때문에 Docker-Volume 포스팅을 참조하기 바란다.


    맨 위 dockerfile에는 없지만 3개 명령어를 추가로 더 보면

  • .dockerignore : 이 녀석은 명령어라기 보다는 Dockerfile같은 파일이다. Dockerfile과 같은 디렉터리에 있는 모든 파일을 Context라고 하는데 그 중 이미지를 생성할때 필요없는 파일들은 해당 디렉토리에 .dockerignore 파일을 만든 후 .dockerigonore 파일에 작성하면 된다. Docker는 Go언어로 작성되어있기때문에 Go문법에 따라 작성해주면 되고, 자세한 건 검색을 해보길 바란다.

  • CMD: 컨테이너가 시작되었을 때(docker run이나 docker start 실행 시) 스크립트 혹은 명령이 실행된다.
    CMD는 dockerfile에서 한번만 사용가능하다. 사용법은

    CMD <명령> 셸(/bin/sh) 또는 CMD [”<실행 파일>”, “<매개 변수1>”, “<매개 변수2>”]

  • EXPOSE: 호스트와 연결할 포트 번호를 설정한다. 사용법은
    EXPOSE <포트 번호=""> 이며 동시에 두개 이상 설정 가능하고 포트를 외부에 노출하려면 docker run 명령의 -p 옵션을 사용해야한다.

    EXPOSE도 VOLUME과 마찬가지이다. 굳이 dockerfile에서 지정해주지 않아도 그냥 docker run의 -p 옵션을 연결해주면 연결이 잘 된다. 이 역시 설정 파일의 정보를 보기 위해 쓰는 것인가 하는 생각은 든다.

    아까 만들었던 poohpooh:test로 다시 똑같이 실험을 해보면 해당 dockerfile에는 EXPOSE를 해주지 않았다.

    하지만 dockerfile을 빌드한 후 docker run의 -p 옵션을 줘보면

    docker run -it -p 2222:22 –rm poohpooh:test /bin/bash

    이를 해석해보면 호스트의 2222번 포트로 접속하면 poohpooh:test의 컨테이너 22번 포트로 접속한다는 뜻이다. 실제로 잘 되어있는지 다른 터미널에서 docker ps로 보면

    dockerfile에서 EXPOSE 명령을 주지 않아도 잘 연결이 되어있음을 확인할 수 있다.

지금까지 각 명령어들에 대해 알아보았고 이렇게 dockerfile에 설정을 해줬으면 이제 dockerfile이 있는 경로에서 docker build 명령어를 통해 dockerfile을 빌드해서 이미지를 만들어 주면 된다(이미 위에서 예를 들다가 다 말해버렸지만…) .

docker build -t pooh:test .

-t 옵션으로 만들 이미지의 이름을 지정해줄 수 있는데 필자는 pooh라는 이름과 test라는 태그를 붙여줬다.

build가 완료되면 잘 만들어졌는지 docker images 명령어로 확인해보면

잘 만들어졌음을 알 수 있다. 다음 포스팅에서는 해당 이미지가 dockerfile 설정대로 잘 만들어졌는지 컨테이너를 띄워보면서 확인해보자.


참고 사이트 :

  • http://ryumso86.tistory.com/2

  • http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter04/02

  • https://subicura.com/2017/02/10/docker-guide-for-beginners-create-image-and-deploy.html

阅读全文 »


[CentOS] another app is currently holding the yum lock; waiting for it to exit...


CentOS에서 yum 사용 시 이런 에러가 발생할 때가 있다. 위의 메시지가 출력되는 원인은 yum이 이미 다른 프로세스로 진행되고 있는 상황에서 다시 yum을 진행하려고 하기 때문이다.

위에 나온대로 보면 waiting for it to exit라고 나와있는 것으로 보아 해결책은 해당 프로세스가 끝날 때까지 기다리는 것인데 언제 끝날지도 모르고 한없이 기다릴 수가 없다. 그래서 2가지 해결방법을 제시한다.


  • 해당 yum 프로세스 정보를 담고 있는 파일을 삭제

먼저 root로 로그인을 한 후에

rm /var/run/yum.pid

이러고 나서 다시 yum을 사용하면

명령어가 잘 수행된다.



  • 해당 yum 프로세스 죽이기

먼저 root로 로그인을 한 후에

ps -aef | grep yum –> yum 프로세스들 중에 yum이 진행되는 것을 확인

kill -9 [pid]로 yum이 사용하고 있는 프로세스 번호를 죽인다.

그러고 나서 다시 yum을 사용하면 명령어가 잘 수행된다.



참고 블로그 : http://blog.net2free.net/43

阅读全文 »


이미지와 컨테이너


이번 포스팅에서는 직접 실습해보면서 이미지와 컨테이너의 개념들을 잡아보도록 하자. 실습 환경은 Ubuntu 16.04 이다.

컨테이너는 이미지를 기반으로 생성되고 실행이 된다. 실행된 컨테이너에서 작업을 하게 되면 컨테이너가 당연히 처음상태와는 달라져 있다. 그러면 이미지도 달라질까? 아니다. 이미지는 컨테이너가 변한다고 이미지가 변하지는 않는다. 이미지는 그냥 그대로 있다. 비유를 들어보면 iso파일로 vm을 만들어 사용한다고 해서 iso파일이 변하지 않는 것과 같은 맥락이라고 생각하면 된다.

그러면 처음 이미지에서 뭔가를 추가해놓은 것을 이미지로 만들 수는 없을까? 있다. 하지만 이미지로 바로 추가할 수는 없고 컨테이너를 실행시킨 후 추가하고 싶은 것을 추가한 뒤 이를 이미지화시켜주면 된다. 간단하게 예를 들어보자.

저번 포스팅 때 centos 이미지를 다운받았었다(만약에 없다면 docker pull centos 입력). centos에 mysql이 설치된 이미지를 만들어보자. 저번처럼 centos 이미지를 컨테이너로 실행해보면

docker run -it centos:latest /bin/bash

잘 실행이 된다. 그리고 mysql이 있는지 버전을 확인해보면 mysql이 설치되지 않았으므로 당연히 command not found가 뜬다. 이 컨테이너에 mysql을 설치해보자.

yum update

yum install mysql

잘 설치가 됐는지 mysql –version으로 확인해보면

아까는 command not found가 떴지만 지금은 mariadb 버전이 나온다(CentOS 7은 mysql을 설치하면, mariadb가 설치됨).

이제 이 컨테이너를 다시 이미지화시켜보자. 컨테이너를 이미지화시키려면 commit 명령어를 써줘야 한다.

docker commit <옵션> <컨테이너명 or="" 컨테이너="" ID=""> <이미지 이름="">:<태그>

필자는 옵션이 따로 없어서 옵션을 주지 않고 commit을 했다. 다른 터미널(이를 이제부터 2번 터미널이라고 하겠음)을 하나 띄워서 docker ps를 통해 실행되고 있는 컨테이너명이나 컨테이너 ID를 알아내고 그 뒷부분은 내가 정해줄 이미지 이름과 태그를 써주면 된다.

그걸 바탕으로 명령어를 입력해보면

docker commit d7d86b17d551 centos:mysql

이를 해석해보면 해당 컨테이너 상태를 centos:mysql이라는 이름으로 이미지로 만들겠다는 말이다. 필자의 경우 centos에다가 mysql을 추가했기 때문에 저런 식으로 이름을 지은 것이지만 짓고 싶은대로 마음대로 지어주면 된다. 잘 생성되었는지 터미널에서 docker images를 입력해보면 다른 이미지가 하나 더 생성되었다. 새로 생성한 이미지를 실행시킨 컨테이너에 mysql이 설치되어있는지 확인하기 위해 해당 컨테이너에 접속해서 확인해보자.

아까와는 다르게 mysql –version을 입력했을 때 command not found가 아닌 mysql 버전이 잘 나옴을 확인할 수 있다.

정리하면 이미지 A를 실행시킨 컨테이너에서 어떤 작업을 해서 내용을 변화시킨다고 해도 이미지 A는 절대 변하지 않고 변화시킨 컨테이너의 내용을 저장하고 싶으면 해당 컨테이너를 commit해서 이미지 B로 만들어야 한다.
그 이유는 이미지 B로 만들지 않으면 컨테이너를 삭제한 후 다시 올렸을 때 이미지 A의 상태 즉, 변경사항이 저장되지 않은 상태의 컨테이너가 실행되기 때문이다. 이미지 B를 만들고 이미지 B를 실행시킨 컨테이너의 내용를 확인해보면 변화된 상태가 적용이 되어있을 것이다.

참고 블로그 : http://pyrasis.com/Docker/Docker-HOWTO

阅读全文 »