Docker에서 Ubuntu 20.04 사용하기

Pt J·2020년 8월 28일
9

Story Of My Life

목록 보기
4/31
post-thumbnail

사실 작업환경 자체도 Ubuntu 20.04다.
다만, Docker에 이 컨테이너를 만드는 건 내 작업환경과는 별개의 테스트 환경을 구축하기 위함이다.
내 로컬에 테스트 환경을 구축하는 김에 소소한 기록을 남겨본다.

Docker 설치

Docker를 설치하는 방법은 공식문서에 친절하게 설명되어 있다.
...라고 하지만 사실 나는 snap 명령어를 통해 설치했다.

$ snap install docker

스냅스토어의 배포 기록을 보면 알 수 있지만
snap에서 몇 년동안 Docker의 최신 버전을 지원하지 않아
한동안 이를 통한 Docker의 설치는 비권장이긴 했지만 이제는 다시 지원한다.

현재 설치되어 있는 버전을 확인해보면...

peter@hp-laptop:~$ docker --version
Docker version 19.03.12, build 48a66213fe
peter@hp-laptop:~$ 

현재 배포되어 있는 가장 최신 버전...


어라 뭔가 버전이 안맞는ㄷ......

아무튼 설치되었으면 다음을 넘어간다.

권한 설정

Docker를 사용할 땐 기본적으로 sudo를 붙여 명령해야 한다.
그러나... sudo를 엄한 데 잘못 붙였다가는 의도치 않은 문제를 직면할 수 있다.
따라서 현재 사용자에게 Docker에 대한 권한을 부여해야 한다.

$ usermod -aG docker $USER

echo $USER를 해보면 알겠지만 $USER는 현재 사용자를 나타내는 환경 변수다.
이 명령어는 $USER의 secondary group(-G)으로 docker 그룹을 추가(-a)한다는 것이다.

여담: primary group과 secondary group
Linux 사용자는 여러 개의 그룹에 속해 있을 수 있으며
그 중 하나는 primary group이고 나머지는 secondary group이다.
primary group의 default값은 사용자 이름과 같은 이름의 그룹이며
ls -l 명령어를 사용했을 때
권한, 링크수, 소유자, 소유그룹, 크기, 생성시점, 파일 이름을 확인할 수 있는데
파일을 생성하면 그 파일의 소유그룹은 생성자의 primary group으로 설정된다.
그리고 그 파일의 그룹 권한은
해당 그룹을 primary 또는 secondary group으로 가진 이들에게 적용된다.
앞서 언급된 usermod 명령어에서 -G 대신 -g를 사용하면
해당 사용자의 primary group을 해당 그룹으로 변경할 수 있다.

그룹을 등록했으면 docker를 재시작한 시점부터 sudo 명령어를 생략할 수 있다.

$ service docker restart

간혹 docker 그룹을 찾지 못해 그룹을 추가할 수 없다는 오류가 날 수 있는데
Docker를 재설치하면 금방 해결된다고 한다.
왜 안되지? (재설치 후) 왜 되지?

Ubuntu 20.04 설치

내려받기

자, Docker를 설치했으면 이제 우분투 이미지를 내려받아 컨테이너를 생성해보자.
이미지를 내려 받으려면 docker pull 명령어를 사용한다.

$ docker pull ubuntu:20.04

특정 버전을 내려받고자 한다면 위와 같이 버전명을 명시해주어야 하며
가장 최신 안정화 버전을 내려 받고자 하면 다음과 같이 할 수 있다.

$ docker pull ubuntu:latest

버전명을 붙이지 않으면 default는 latest라고 한다.

사실 이렇게 따로 내려 받지 않아도 컨테이너를 생성할 때 로컬에 이미지가 있는지 확인하고
존재하지 않을 경우 Unable to find image 'ubuntu:20.04' locally 라며
알아서 내려 받으므로 생략해도 되는 과정이다.

컨테이너 생성하기

컨테이너를 생성하는 방법은 여러 가지가 있다.
그냥 명령어로 직접 생성할 수도 있고, Dockerfile을 사용할 수도 있고,
여러 개의 이미지를 함께 사용할 경우 docker-compose를 이용하기도 한다.
하지만 우리는 단일 이미지이며 매번 새로 생성하는 게 아니라 만들어놓고 계속 쓸 예정이므로
그냥 명령어로 직접 생성하는 방법을 사용하겠다.

Dockerfile을 사용하는 경우는 보통 --rm 옵션을 통해 컨테이너를 멈추면 자동 삭제되게 하고
사용할 때 매번 Dockerfile을 새로 build하여 사용한다.
이 때, 내부 데이터는 사라지게 되므로 필요한 데이터는 외부에 저장해놓고 복사해서 사용한다.
물론 그 복사 코드도 Dockerfile 안에 작성된다.
컴파일 할 때 Makefile을 사용해본 사람은 알겠지만 이런 방식은
처음 배울 땐 복잡하고 어려워보이지만 익숙해지면
미리 작성만 잘 해두면 매번 복잡한 명령을 할 필요 없이 쉽게 실행할 수 있다는 장점이 있다.

docker-compose를 사용하는 경우는 여러 개의 이미지를 함께 사용하는 경우로
docker-compose.yml 파일에 전체적인 설정을 작성하고
개별 이미지를 관리하는 하위 디렉토리에 각각의 Dockerfile 및 설정 파일을 작성한다.
예를 들어, ELK stack을 사용한다고 하면
docker-compose.yml이 존재하는 디렉토리에 하위 디렉토리로
elasticsearch, logstash, kibana의 디렉토리가 각각 존재하며
그 안에 그들의 Dockerflile 및 설정 파일이 존재하는 구조다.
그리고 docker-compose build 명령어를 통해 한 번에 build하고
docker-compose up 명령어를 통해 한 번에 실행할 수 있는데
일단 우리가 사용할 건 이 방식이 아니므로, 이건 언젠가 기회가 되면 다시 이야기하도록 하자.

Dockerfile에 대한 자세한 설명은 여기에서,
docker-compose에 대한 자세한 설명은 여기에서 확인할 수 있다.
공식 문서만큼 정확한 것은 없으니 영어라고 겁먹지 말도록 하자.

여러 가지 옵션

컨테이너를 생성할 땐 여러 가지 설정을 해줄 수 있다.
그것은 대체로 생성 후에도 수정할 수 있지만 때로는 정말 번거로운 과정이 되므로
무작정 검색 결과를 보며 따라하기 보다는 필요한 옵션이 무엇인지 판단하여 작성하도록 하자.

그 무작정 따라함 방지를 위해 먼저 몇 가지 옵션들을 소개한 뒤에 컨테이너를 생성하겠다.
모든 걸 다 설명할 수는 없겠지만 여기서 설명하는 모든 내용은
터미널에서 다음 명령어를 통해 영어로 확인할 수 있다.

$ docker run --help
  • -d : daemon 모드 실행, 또는 detach 모드 실행이라고 한다. 컨테이너를 background로 실행하며 정상적으로 실행될 경우 컨테이너의 ID를 출력한다.
  • -e : environment의 줄임말로, -e KEY=value와 같이 사용하며 컨테이너에 환경변수를 설정한다. 전달해야 할 환경변수가 여러 개라면 -e KEY0=value0 -e KEY1=value1와 같이 반복해서 사용할 수 있다.
  • -i : interactive의 줄임말로, 표준 입력을 받기 위한 옵션이다.
  • -p : port의 줄임말로 특정 포트를 컨테이너에 포트 포워딩하기 위해 사용한다. -p containerPort:hostPort와 같이 사용하며 -p containerPort:hostPort/protocol의 형태로 TCP 같은 프로토콜을 지정해줄 수도 있다. 환경변수와 마찬가지로 이 녀석도 여러 개 설정해주고 싶다면 반복해서 사용할 수 있다.
  • -t : 가상 터미널 환경을 제공해주는 옵션이다.
  • --name : --name containerName와 같이 사용하며 컨테이너의 이름을 지정한다.
  • --rm : 앞에서도 잠깐 이야기했지만 컨테이너가 종료되면 이를 자동으로 삭제한다.

일단 이 정도만 알고 넘어가자.
docker run에 대한 설명은 공식 문서에서도 확인할 수 있다.

docker run 실행

자, 그러면 이제 본격적으로 컨테이너를 생성할 시간이다.
docker run 명령어의 기본적인 사용 방법은 다음과 같다.

$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

[] 안에 있는 내용은 선택적으로 사용하는 녀석들이며
대문자로 적혀 있는 부분은 적절한 텍스트로 대체해야 하는 부분이다.
OPTIONS에는 우리가 조금 전에 살펴 보았던 여러 가지 옵션들이 올 수 있고
COMMAND로는 이 컨테이너가 실행할 명령어를 전달할 수 있다.
ARG는 글쎄, 사실 이걸 사용하는 경우는 보지 못했다.

우리는 다음 명령어를 통해 컨테이너를 생성할 것인데,
필요에 따라 위를 참고하여 적절한 옵션을 추가하도록 하자.

$ docker run -it --name test-ubuntu ubuntu:20.04 /bin/bash

여담으로, 검색을 통해 볼 수 있는 명령어 중에 줄 끝에 있는 \
아직 명령어가 안끝났으며 다음줄로 이어진다는 의미인데
개행을 하지 않고 한 줄에 모두 적을 경우 생략한다.
우리가 사용한 명령어는 짧아서 그것을 사용하지 않았지만, 말 그대로 여담.

아무튼 위 명령어를 실행하면 Digest, Status 정보가 출력되고
root@asdfasdfasdf:/#와 같은 프롬프트가 뜨는 것을 알 수 있다.
@ 뒤에 오는 것은 컨테이너 ID다.

컨테이너 실행하기

docker run을 통해 실행한 컨테이너는 exit을 통해 나가면 종료된다.
다음 명령어를 통해 실행 중인 컨테이너를 확인할 수 있는데 확인해보면 보이지 않을 것이다.

$ docker ps

여기에 -a 옵션을 주면 종료된 컨테이너까지 확인할 수 있는데 그럼 그제서야
Exited (0)이라며 언제 종료되었는지까지 친절하게 알려준다.

아무튼 이제 컨테이너가 생성되었으므로 이 녀석을 시작하면 실행할 수 있게 된다.
컨테이너는 docker start 명령어로 시작하며 컨테이너 ID 또는 이름을 사용할 수 있다.
그런데 ID는 임의의 숫자와 문자로 구성되어 기억하기 어려우므로
생성할 때 --name 옵션으로 이름을 지정해주고 사용하는 편이 편하다.
우리가 앞서 만든 컨테이너를 시작하려면 다음과 같이 입력하면 된다.

$ docker start test-ubuntu

정상적으로 시작되었다면 방금 입력한 컨테이너 ID 또는 이름이 뜨는 것을 확인할 수 있다.
이제 다시 docker ps를 해보면 이 녀석이 보일 것이다.

이렇게 시작한 컨테이너에 접근하기 위해서 우리는 이 컨테이너의 /bin/bash를 실행할 것이다.
컨테이너의 특정 명령을 실행하기 위해서는 docker exec을 사용한다.

$ docker exec -it test-ubuntu /bin/bash

이제 아까와 같이 root@asdfasdfasdf:/#와 같은 프롬프트가 뜬다.
컨테이너 내부에서 작성한 것이 잘 저장되는지 확인하기 위해 테스트 파일을 하나 만들어보자.

$ touch testfile

testfile이라는 이름의 0byte짜리 파일, 즉 빈 파일을 하나 만들었다.
이 상태로 exit을 하면 다시 나갈 수 있는데
이번에 다시 docker ps를 해보면 아직 컨테이너가 살아있다.
조금 전과 동일한 방법으로 도커 컨테이너의 bash를 열고 ls를 해보면
우리가 만든 테스트 파일이 그대로 존재한다.

자, 이제 다시 나가서 컨테이너를 정지시켜 보자.
앞서 컨테이너를 시작할 때 사용한 명령어에서 startstop으로 바꾸면 된다.

$ docker stop test-ubuntu

이제 docker ps를 통해서는 이 컨테이너를 확인할 수 없고
docker ps -a를 통해 종료된 것을 확인할 수 있다.
이 상태에서는 docker exec을 시도해보아도 실행되지 않는다.
다시 컨테이너를 시작해 bash로 접근해보면 아직 테스트 파일이 존재하는 것을 볼 수 있다.
즉, 컨테이너를 나가거나 정지해도 데이터는 보존된다는 것을 알 수 있다.

기본 설정

자, 우분투 컨테이너를 설치했으니 이제 한 번 사용해볼까?
라고 하다가 시작부터 당황하는 경우가 있다.
vinano도 안되면 대체 뭘 사용할 수 있지?
apt install vim을 해보아도 뭔가 오류가 나는데?

사실 이건 매우 단순한 문제다.
apt 패키지를 업데이트 하도록 하자.

root@asdfasdfasdf:/# apt update

이제 apt를 통해 무언가 설치할 수 있을 것이다.
필요에 따라 apt 서버가 너무 느리다고 생각되면 국내 서버인
다음카카오 우분투 미러 사이트로 서버를 변경할 수 있다.
apt update를 수행한 후라면 vi를 통해 다음과 같은 파일을 열어

$ vi /etc/apt/source.list

http://kr.archive.ubuntu.com/ubuntu/ 또는 http://archive.ubuntu.com/ubuntu/
http://ftp.daumkakao.com/ubuntu/ 로 치환하면 된다.
kr.이 붙는지는 경우에 따라 달라지더라.
vi를 통해 문자열을 한 번에 치환하고자 한다면 다음과 같이 할 수 있다.

:%s/kr.archive.ubuntu.com/ftp.daumkakao.com/g

물론 주소에 kr.이 없다면 생략하고 입력하도록 하자.

apt update를 하기 전이라면 sed 명령어를 통해 치환할 수 있다.
이 녀석은 기본적으로 치환한 결과를 보여주기만 하고 원본에 반영하지 않지만
-i 옵션을 주어 원본에 반영하도록 할 수 있다.

$ sed -i 's/kr.archive.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/source.list

이렇게 서버를 변경하고 나서는 다시 apt update를 해주어야 한다.
이제 나머지는 각자 필요한 패키지를 설치하여 작업하면 된다.

profile
Peter J Online Space - since July 2020

0개의 댓글