[LG CNS AM Inspire Camp 1기] Docker (2) - Dockerfile 왜 사용하는가?

정성엽·2025년 2월 13일
0

LG CNS AM Inspire 1기

목록 보기
48/53

INTRO

이전 포스팅에서는 Docker에서 사용되는 레이어드 아키텍처라는 개념과 간단한 커맨드를 입력하고 로그를 살펴보는 식으로 정리했다.

이번 포스팅에서는 이전에 설명없이 작성했던 부분에 대해서 조금 더 자세히 정리해보려고 한다 👀


1. Dockerfile을 사용하는 이유

이전 포스팅에서 인스펙션이 가능한 Dockerfile을 사용하는 방법이 제일 좋다고 설명했다.

인스펙션이 가능한 이유는 Dockerfile에 우리가 진행할 작업 내용이 적혀있기 때문이다.

즉, 우리가 작업할 내용을 Dockerfile에 정리해서 이미지를 빌드하면 한번에 처리가 가능하다는 장점이 있다.

이 부분을 조금 더 자세히 살펴보기 위해 간단한 실습을 진행해보자

2. [LAB] ubuntu를 사용하여 HTML파일 접근하기

실습의 목적을 조금 더 자세히 설명하면 다음과 같다.

실습 목적
로컬에서 생성한 HTML파일을 ubuntu 서버를 통해 웹브라우저로 접근하기

이를 위해서 우리는 ubuntu 컨테이너와 이 컨테이너에 apache 서버를 설치해야 한다.

그리고 컨테이너를 통해 띄워진 아파치 서버로 접근하면 된다.

💡 HTML 파일 생성

우선 우리가 ubuntu의 아파치 서버로 띄울 Hello.html 파일을 작성해보자

Sample Code

<!DOCTYPE html>
<header>
  <title>My Lab 01</title>
</header>
<html>
  <div>
    <h1>Hello</h1>
  </div>
</html>

💡 ubuntu 컨테이너 실행

Dockerhub에 존재하는 ubuntu를 사용하여 바로 컨테이너를 띄울 수 있다.

우선 실습에 사용할 ubuntu 컨테이너를 실행시켜보자

◉ 커맨드 - ubuntu 컨테이너 실행
docker container run -p 8080:80 --name myweb --rm ubuntu

우리는 포트 바인딩을 통해 Host의 포트 8080을 ubuntu 컨테이너의 포트 80과 매핑시켜준다.

여기서 포트 80을 매핑시켜주는 이유는 ubuntu 컨테이너에 설치할 apache가 기본적으로 http 통신으로는 80포트를 사용하기 때문이다.

--rm : 여기서 사용된 --rm 옵션은 컨테이너가 정상적으로 종료되면 컨테이너도 같이 삭제되도록 설정하는 옵션이다.

이처럼 실행해보면 화면은 다음과 같이 뜨게된다.

Result View

보다시피 명령어를 입력하자마자 프롬프트가 다시 호스트로 넘어온다.
그래서 container의 상태를 확인해보면 빨간색 박스와 같이 Exited 된 모습을 볼 수 있다.

왜 이렇게 되는걸까?

💡 제어권 반납

그 이유는 컨테이너가 종료되었기 때문이다.

조금 더 정확하게 설명하면 컨테이너 내부에서 동작할 프로세스가 없기 때문이다.

기본적으로 컨테이너를 실행시키면 그 내부에서 동작할 프로세스가 존재한다.

프로세스가 동작이 완료되면 제어권을 다시 컨테이너로 반납하게되고, 컨테이너는 모든 프로세스의 제어권을 반납받으면 호스트로 제어권을 반납하게 된다.

따라서 ubuntu를 실행시키더라도 실행할 프로세스가 없기 때문에 다시 호스트로 제어권을 반납하여 비정상적으로 컨테이너가 종료된다.

이러한 맥락으로 --rm 옵션도 제대로 동작하지 않아 컨테이너가 삭제되지 않는 것이다.

💡 ubuntu 가상 터미널 실행

이전 포스팅에서 -it 라는 옵션에 대해서 정리하고 넘어갔다.

이는 간단하게 가상터미널을 실행하여 컨테이너를 제어할 수 있도록 도와주는 옵션이다.

즉, ubuntu docker 가상 터미널을 실행하게 되면 사용자가 입력하는 커맨드를 기다리는 상태가 되기 때문에 제어권을 바로 반납하지 않는다.

이 방법을 사용해서 기존 컨테이너는 삭제하고 다시 띄워보자

◉ 커맨드 - ubutnu 컨테이너 실행 + 가상터미널 실행
docker container run -p 8080:80 -it --rm --name myweb ubuntu


Result View

실행결과 가상터미널에 정상적으로 접근한 모습을 확인할 수 있다.

이제 여기에 apache 서버를 설치하고 나가보자

💡 ubuntu에 apache 설치

◉ 커맨드 - ubuntu에 apache 서버 설치

  • apt-get update : 현재 패키지 정보를 최신으로 가져온다.
  • apt-get install apache2 : apache 서버를 설치
  • apachectl : apache 서버 실행
    Result View

서버네임이 설정되지 않아 apache 서버가 실행되지 않는 상황이다.

따라서, apache 서버네임을 환경변수에 추가하자

◉ 커맨드 - apache 서버네임 추가
echo "ServerName localhost" >> /etc/apache2/apache2.conf

여기서 >> 는 리눅스 커맨드로 파일 맨 뒤에 해당 내용을 추가하겠다는 의미이다.

참고로 > 는 덮어쓰기를 의미한다.

◉ 커맨드 - apache2.conf 확인
cat /etc/apache2/apache2.conf


Result View

cat으로 해당 파일을 확인해보면 마지막에 ServerName이 정상적으로 추가된 내용을 확인할 수 있다.

다음으로 apache 서버를 다시 실행시켜주자

💡 HTML 파일을 컨테이너로 복사하기

우리가 컨테이너로 호스팅되는 주소로 접근하여 HTML을 확인하려면 당연히 우리가 설치한 ubuntu쪽에 HTML파일이 존재해야 한다.

따라서, VSCode에서 작성한 HTML 파일을 컨테이너 내부로 옮겨줘야 한다.

우선 우리는 컨테이너를 가상 터미널로 접속하여 실행하고 있다.

이전에 --rm 옵션을 추가했기 때문에 exit로 가상 터미널을 나간다면 컨테이너가 제어권을 반납하고 종료되어 삭제된다.

여기서 attach 모드로 나가기 위해서는 Ctrl + p + q 키를 동시에 누르면 된다. (포그라운드로 실행)

이제 터미널에서 복사하는 커맨드를 입력하자

◉ 커맨드 - HTML -> ubuntu 컨테이너 내부의 특정 디렉토리로 복사
docker container cp Hello.html myweb:/var/www/html

여기서 현재 디렉토리가 복사할 대상 (Hello.html)이 있는 디렉토리여야 한다.

Result View

정상적으로 복사되었다고 나온다.

현재 컨테이너는 실행중이므로 http://localhost:8080/Hello.html 로 접속하면?

Result View

로컬에서 작업한 HTML파일을 컨테이너의 호스팅 주소로 접속하여 확인할 수 있다.


3. Dockerfile 사용하기

위처럼 컨테이너에서 로컬에 있던 파일을 띄우기 위해서는 너무 번거로운 작업을 하나씩 진행해야 한다.

따라서, 우리는 Dockerfile을 사용하여 이 과정을 한번에 처리할 수 있다.

Dockerfile을 동일한 로컬 디렉토리에 생성해보자

Sample Code

FROM ubuntu
RUN apt-get update
RUN apt-get install apache2
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
COPY hello.html /var/www/html/
CMD apachectl start

우리가 이전에 진행했던 순서대로 Dockerfile을 구성한 것이다.

apache 서버를 설치하고 ServerName을 설정하고 파일을 복사하고 마지막으로 apache 서버를 실행하는 내용이 담겨있다.

이제 Dockerfile을 이미지로 빌드해보자

💡 Dockerfile 빌드하기 - 1

◉ 커맨드 - Dockerfile 빌드
docker image build -t mywebserver:v1 .


Result View

Dockerfile을 빌드하면 위처럼 오류가 뜬다.

로그를 확인해보면 Dockerfile의 RUN apt-get install apache2 쪽에서 오류가 발생했고, 사용자의 입력값이 필요한 부분에서 Abort가 입력된 모양이다.

따라서, Dockerfile을 빌드하는 과정에 사용자 입력이 필요한 경우 에러가 발생함을 알 수 있다.

그럼 이건 어떻게 해결할 수 있을까?

💡 Dockerfile 빌드하기 - 2

모든 요청에 대하여 y를 넘기도록 하면 된다.

우선 작성한 도커 파일을 확인해보자

Sample Code

FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y apache2
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
COPY hello.html /var/www/html/
CMD apachectl start

우선 이전에 오류가 발생했던 RUN apt-get install apache2 부분에 -y 옵션을 추가했다.

이렇게 설정하면 모든 질문에 대하여 y라는 대답을 넘기게 된다.

Dockerfile을 잘 살펴보면 이전에는 없던 ENV DEBIAN_FRONTEND=noninteractive 가 추가된 모습을 볼 수 있다.

y로 대답하는 경우가 아니더라도 우리는 timezone 설정, 언어 설정 등등 사용자의 선택을 요구하는 경우가 존재한다.

이러한 요구사항을 없애기 위해 ubuntu 이미지를 사용하여 빌드할 때, DEBIAN_FRONTEND 라는 환경변수에 noninteractive를 넣어주기 위한 코드라고 생각하면 된다!

이제 업데이트된 Dockerfile을 기반으로 이미지를 다시 빌드해보자

Result View

이번에는 제대로 빌드된 모습을 확인할 수 있다.

다음으로 이전에 하나씩 설정했던 이미지를 삭제하고 이번에 새로 빌드한 이미지를 사용하여 컨테이너를 생성하고 실행시켜보자

◉ 커맨드 - 컨테이너 빌드
docker container run -d -p 9090:80 --rm mywebserver:v1


Result View

보다시피 위 커맨드를 실행해서 컨테이너를 띄웠으나, 확인해보면 방금 띄운 컨테이너는 확인되지 않는다.

왜 그럴까?

💡 Apache를 포그라운드로 실행하기

그 이유는 바로 apache가 기본적으로 백그라운드로 실행되기 때문이다.

컨테이너는 메인 프로세스 (PID=1)이 실행되는 동안에는 살아있다.

하지만, apache를 백그라운드로 실행하게 되면 메인 프로세스는 역할이 끝나서 종료된다.

따라서, 컨테이너도 같이 종료되며 --rm 옵션에 의해 컨테이너가 종료됨과 동시에 삭제되는 것이다.

이 문제를 해결하기 위해서는 apache를 포그라운드로 동작시키면 된다.

그 설정을 Dockerfile에 추가해보자

Sample Code

FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y apache2
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
COPY hello.html /var/www/html/
CMD apachectl -D FOREGROUND

마지막 CMD 쪽에 -D FOREGROUND 옵션이 추가된 모습을 볼 수 있다.

다시 이미지를 빌드하고 실행시켜보자

Result View


보다시피 Dockerfile로 생성한 컨테이너 9090포트로 접근해도 정상적으로 HTML파일이 확인되고 있다!


OUTRO

필자는 간단한 실습으로 Dockerfile을 사용할 때 얻을 수 있는 장점을 보여주고 싶었다.

Ubuntu에 Apache를 설치하고 HTML 파일을 호스팅하는 과정을 통해, Dockerfile 없이 하나하나 명령어를 입력하는 방식과 Dockerfile을 사용하는 방식의 차이를 확실히 느낄 수 있었을거라 생각한다.

포스팅을 작성하기 위해 실습을 다시 정리하면서 진행했는데, 도커 커맨드에 조금 더 익숙해진 것 같다 👊

profile
코린이

0개의 댓글

관련 채용 정보