Docker

Docker 입문 (on M1 Mac) : Network, Command, FileSystem

졸려질려 2022. 4. 7. 17:04
반응형

유튜브의 출처 : 생활코딩 Docker 입문수업 의 내용들과 실습해본 사진들을 같이 넣어서 정리한 글입니다.

이전 글 : https://choboit.tistory.com/89

 

Docker 입문 (on M1 Mac) : Docker, Docker Install, Docker Basic Command

본 글은 이고잉님의 "생활코딩 Docker 입구 수업"을 보면서 실제로 해보고, 그 과정을 정리해둔 글이다. 글의 순서 또한 강의 영상의 순서에 따라 정리하였고, 글의 내용은 "생활코딩 Docker 입문수

choboit.tistory.com


5. 네트워크

 Docker에서 사용하는 많은 프로그램들이 네트워크를 사용하므로, Docker를 원활히 사용하기 위해서는 네트워크 지식이 필요하다.
Docker의 네트워크 방식을 알아보기 전에, 기존의 WebServer 네트워크 방식이 어떤지 알아볼 필요가 있다. 수업 영상에서 좋은 그림이 있어서 스크린샷(출처 링크)을 찍어왔다.

WebServer 통신 방식 (출처: 생활코딩 Docker 입문수업 - 5. 네트워크)

 위 사진은 Web browser가 있는 컴퓨터와 Web server가 구축된 컴퓨터 간의 통신이라 봐도 된다. Web server가 구축된 컴퓨터의 도메인을 example.com 이라 명명하고, Web browser에서 example.com의 index.html 파일로 접근한다. "example.com:80"에서 80은 Webserver로 접근하는 Port의 번호를 뜻하며, Apache Web server는 통상 80번 Port를 사용한다. 다시 돌아와서, index.html 요청을 받은 Web server는 80번 Port를 통해 해당 파일을 Web browser에게 전달한다. 하나의 컴퓨터 안에 하나의 Web server가 구축되어 있을 경우 위처럼 통신을 하게 된다. 반면에 Docker는 하나의 컴퓨터 안에 여러 개의 가상 머신을 올리는 것과 비슷하다. 가상 머신과 같은 것을 Container라고 부르는데, 이 Container는 하나의 OS를 가지고 있기 때문에 컴퓨터와 같이 Container만의 Port들을 지니고 있다.

Docker Web server 통신 방식 (출처: 생활코딩 Docker 입문수업 - 5. 네트워크)

 위 그림처럼 Container는 하나의 가상 머신과도 같기 때문에 Host처럼 Container만의 Port들이 존재한다. 그리고, Container를 설치한다고 해서 Host의 Port들과 같은 번호끼리 매칭 시켜주는 것도 존재하지 않는다. Container만 설치한 상황에서 Web browser가 example.com:80으로 index.html을 요청하게 되면, 먼저 Host의 80번 Port로 접근을 한다. Host는 요청을 받아도, Host 안의 File System에서 해당 파일을 찾아보고, 없으면 아무것도 보내줄 수가 없다. (물론, Host 안에 따로 Web server를 구축하지 않거나, 80번 Port를 다른 목적을 위해 listen 상태로 바꾸지 않는다면 애초에 접근을 할 수 없다.) 그렇다면, Host의 80번으로 온 요청을 Container의 80번 Port로 연결을 해주는 과정이 필요할 것이다. 그것을 "Port Forwarding"이라 한다. Docker 명령어는 다음과 같다.

docker run -p [Host Port]:[Container Port] [Image Name]

실제로 Port Forwarding을 하여 Container를 실행시켜보자. Image를 Run하는 명령어에서 "-p" 옵션을 추가한다.

1. Pull "httpd" Image

2. Run Container with Port Forwarding

- Docker Desktop

  1. httpd Image의 [RUN] 버튼 클릭
  2. [Optional Settings] 클릭
  3. <Container Name>과 <Local Host> 설정

- Terminal

docker run --name ws3 -p 8081:80 httpd

Port Forwarding in Terminal

- docker ps : Container들이 잘 생성되었는지 확인

3. Connect to Container's Web Server

브라우저에서 "localhost:8080/index.html" 을 입력하면 위 사진처럼 잘 연결된 것을 확인할 수 있다. 또한, Docker Desktop에서도 로그가 잘 출력된 것을 볼 수 있다. 그리고 8081번 Port와 포워딩을 한 ws3의 로그는 Terminal로 확인해보자.


6. 명령어 실행

 이번에는 Container로 접속하여 각종 명령어를 실행해본다. 먼저 Docker Desktop으로 Container에 접속하는 방법은 다음과 같다.

  1. 접속하고자 하는 Container 클릭
  2. 우측 상단에 [CLI] 버튼 클릭 ([STOP] 버튼 왼쪽)

Docker Desktop - CLI

Terminal에서는 다음 명령어를 사용하면 된다. (docker -exec)

 docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

docker exec [CONTAINER_NAME] COMMAND

 여기까지 봤을 때, Docker Desktop은 [CLI]를 클릭하는 순간, Container의 터미널을 불러와서 로컬 터미널을 사용하는 것처럼 지속적으로 명령어를 입력할 수 있다. 반면에, Terminal에 "docker exec"를 사용하면, 해당 명령어만 실행되고 다른 명령어를 실행하려면 다시 "docker exec"를 입력해야한다. 이런 불편함이 없이 Docker Desktop처럼 쭉 사용하고 싶다면 어떻게 하면 될까?

docker exec ws3 /bin/sh

우선, Container의 Shell을 실행하는 "docker exec ws3 /bin/sh"를 입력한다. Container는 Linux이기 때문에 Shell을 사용할테고, 위처럼 Shell을 열어서 계속 명령어를 넣고 싶은 것이다. 하지만, 위 사진의 첫 명령어 줄을 보면 정상적으로 입력이 됐으나, 우리가 원하는 형태로 변하지 않는다. Shell을 실행하는 데는 성공했으나, 그 Shell가 세션을 맺어서 지속적으로 연결하지 않는다. 그래서 exec 명령어에 "-i"와 "-t" 옵션을 혼합으로 넣어줘서 다시 실행한다. 그러면 여느 Linux 터미널처럼 로컬 터미널의 출력이 바뀐 것을 볼 수 있다.

- Modify index.html in Container

 이제 원격 접속이 가능해졌으니, Port Forwarding에서 보았던 index.html 파일을 수정하여 "It works!" 문자열을 바꿔보자.
수정하기에 앞서, index.html이 Container의 어느 위치에 있는지 알 필요가 있다. 해당 위치는 httpd 문서에서 찾을 수 있다.

 문서에 따르면 index.html 문서는 "/usr/local/apache2/htdocs/" 위치에 있다는 것을 알 수 있다. 이제 터미널을 통해 해당 파일을 열어보자. 

 ws3 Container의 index.html이 있는 위치로 이동했다. Container는 이제 막 생성된 Linux 이기 때문에, Visual Studio Code와 같은 에디터는 없을 것이다. 그럼 vi나 nano로 열어봐야 한다.

 vi나 nano로 index.html을 열려고 하는데, 위 이미지처럼 vi나 nano 같은 명령어를 찾을 수 없다는 에러가 출력된다. Docker의 Container는 최대한 용량을 줄이려 하기 때문에, 기본적으로 vi나 nano를 지원하지 않는다. "head"나 "tail" 같이 기본 명령어는 적용이 되어서 index.html의 안을 볼 수는 있다. 하지만, 우리가 원하는 것은 저 파일을 수정하는 것이다. 따라서, vi나 nano를 따로 설치해서 수정하도록 하자.

apt update

apt install nano

 위 두 명령어를 통해 nano를 설치한다. 그러면 index.html을 에디터로 열어볼 수 있다.

 index.html 안에 "It works!" 문자열을 "Hello Docker!"로 수정하고, 저장한다. (control + x -> y -> enter)
그리고 브라우저로 index.html을 열어보면 문자열이 수정된 것을 확인할 수 있다.


7. 호스트와 컨테이너의 파일시스템 연결

 방금 Container에 접속하여 index.html을 수정 해보았다. 이제 index.html을 비롯하여 그에 맞는 추가 소스 코드를 개발하려면 Container의 터미널에 접속해서 작업을 진행하면 될 것이다. 그런데, 이대로 정말 편할까? Docker의 Container는 쉽게 생성하고, 쉽게 삭제하는 편의성을 제공하고 있다. 그런데 Container에만 작업물이 있다면 쉽게 삭제하는 편해지지 않을 것이다. 게다가, 다른 환경의 Container를 생성해서 소스코드를 옮기려면, 호스트로 코드를 옮기고 다시 업로드해야 하는 부담감이 있을 것이다. 이번에는 호스트의 폴더와 작업하고자 하는 Container의 폴더를 연동하여 호스트에서 작업한 것이 실시간으로 Container의 코드에 반영되도록 해보자.

 이전까지 사용했던 ws2와 ws3 Container들을 삭제하고, ws1 이라는 이름에 8888번 포트를 포워딩하고, 호스트의 "~/Document/VSC/htdocs" 폴더를 "/usr/local/apache2/htdocs/" 와 연동하여 Container를 생성한다. "/usr/local/apache2/htdocs/" 경로는 index.html이 있던 기본 경로이다. "~/Document/VSC/htdocs" 경로는 방금 막 생성되었다. 그래서 htdocs 폴더 안에는 아무런 파일이 없다. 이제 호스트의 htdocs 폴더 안에 같은 이름의 index.html을 생성하고 다음과 같이 코드를 추가한다.

 그리고 호스트의 브라우저에서 "localhost:8888/index.html" 로 접속하여 Container의 index.html을 열어본다.

ws1 Container는 파일 시스템을 연동하는 명령어를 입력하면서 새로 생성되었던 Container이다. httpd Container를 새로 생성했을 때 index.html에서는 "It works!" 문자열이 있었지만, 이번에는 호스트의 index.html처럼 "Hello Docker!" 문자열이 출력된 것을 볼 수 있다. 좀 더 확인해보기 위해서 Container의 터미널로 index.html을 출력해보자.

 vi나 nano를 새로 설치하기 귀찮아서 "head" 명령어를 통해 상단 10줄을 출력해보았다. Container의 index.html도 호스트의 index.html과 내용이 같다는 것을 확인할 수 있다.

 추가로 생각해볼 것은 index.html만 연동한 것이 아니라, htdocs라는 폴더를 연동하는 옵션을 설정했다. 따라서 index.html이 아닌 다른 파일을 생성했을 때 Container에도 생성이 되는지 확인해보자.

 간단하게, htdocs 폴더 안에 "app.js" 파일을 생성하고, index.html이 참조하도록 코드를 수정했다. "app.js" 에는 "Hello Docker!" 문자열을 클릭하면 "Hello Docker! Gooood!!" 문자열로 바뀌도록 코드를 구성했다. 두 파일을 저장하고 다시 브라우저로 접속해보자.

 app.js 가 잘 적용되는 것을 볼 수 있고, 파일 시스템 간에 연동을 했기 때문에 호스트 폴더 안에 변화가 모두 Container에도 적용된다는 것을 확인 할 수 있다. 이제는 생성한 Container에 필요한 작업을 호스트에서 할 수 있게 되었다.

반응형