[클라우드/Docker 기본(7) - Dockerfile로 이미지 만들기]

SooYeon Yeon·2022년 8월 30일
0

클라우드 Docker

목록 보기
8/24

도커 이미지 만들기

  • 컨테이너(linux의 cgroup, namespace)는 이미지를 통해 배포된다.
  • 생성된 컨테이너는 이미지의 내용을 그대로 풀어놓는 것과 같으므로 read할 수 있고, write는 안된다.
  • 생성된 컨테이너는 이미지로부터 읽을 수 있는 부분과 추가적으로 자체 작성할 수 있는 레이어로 구성된다.
  1. 동작중인 컨테이너를 이미지로 변환 → commit
  2. tar 파일을 이용하여 내용을 이미지로 전송하는 방식으로 새로운 이미지 만들기 → image save
  3. Dockerfile 이용하여 이미지 생성하기 (주로 사용)
    • 일종의 명세서를 작성하는 방법

DockerFile 이용하기

파일 이름을 Dockerfile로 안해도 되긴하지만, 이름을 다르게하면 옵션을 줘야함

ex) Dockerfile1이라면 빌드시 -f 옵션을 사용한다.

docke build -t myimg:1.0 -f dockerfile1 (이미지 생성)

일반적으로는 두 개 이상의 이미지를 생성하고자 한다면 별도의 디렉토리를 만들고, 각 디렉토리에서 별도의 Dockerfile을 생성하는 형식으로 이미지를 만들게 된다.

.은 현재 위치에 Dockefile 있다는 것

rapa@rapa:~/0818$ touch Dockerfile
rapa@rapa:~/0818$ vi Dockerfile 
rapa@rapa:~/0818$ docker build -t test:1.0 .
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM centos:7
 ---> eeb6ee3f44bd
Successfully built eeb6ee3f44bd
Successfully tagged test:1.0
  • 이미지를 확인해보면
  • centos와 방금 만든 test는 같은 이미지 (ID가 똑같기 때문, 공간을 두배 차지하는 것 아님)
rapa@rapa:~/0818$ docker image ls
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
wordpress           latest    66b89e8b083b   2 weeks ago     609MB
nginx               latest    b692a91e4e15   2 weeks ago     142MB
dustndus8/mynginx   blue      b692a91e4e15   2 weeks ago     142MB
dustndus8/mynginx   green     b692a91e4e15   2 weeks ago     142MB
httpd               latest    f2a976f932ec   2 weeks ago     145MB
mysql               5.7       3147495b3a5c   3 weeks ago     431MB
centos              7         eeb6ee3f44bd   11 months ago   204MB
test                1.0       eeb6ee3f44bd   11 months ago   204MB
google/cadvisor     latest    eb1210707573   3 years ago     69.6MB

FROM centos:7

RUN yum -y update

RUN yum -y install httpd

COPY test.tar /var/www/html

ADD test.tar /var/www/html

EXPOSE 80

자주 사용하는 옵션

FROM (필수)이미지의 베이스 이미지 지정
LABEL이미지 작성 목적으로 버전, 타이틀, 설명, 라이선스 정보 등을 작성

LABEL purpose = ‘Nginx for webserver’
LABEL version = ‘1.0’ | |
| RUN | 명령어 작성, 이미지에 패키지 설치, 업데이트 등의 명령을 실행하고자 하는 경우 작성
컨테이너가 아닌 베이스 이미지 자체에 전달하는 명령어
여러번 사용 가능
1. shell 형식 작성 방법
RUN apt -y install nginx
RUN yum -y install httpd

  1. exec 형식 작성 방법
    RUN [”echo”, “이것은 테스트입니다.”] | |
    | CMD | 이미지가 아닌, 이미지에서 컨테이너로 배포될 때 실행할 명령어를 추가할 수 있다.
    예를 들어, 이미지에는 RUN을 이용해 웹서버를 설치하고, CMD를 이용해 컨테이너로 배포될 때 웹서버 데몬(CMD apache2ctl -DFOREGROUND)을 실행하게 된다.
    "Cmd": [
    "nginx",
    "-g",
    "daemon off;"
    ], 은 nginx를 실행시킨다는 것 : CMD [”nginx”,”-g”,”daemon off;”]

"Cmd": [
"httpd-foreground"
], 은 httpd를 실행시키는 것 : CMD | |
| ENTRYPOINT | 컨테이너로 배포될 때 사용하는 명령어
ENTRYPOINT nginx -g ‘daemon off;’ | |
| COPY | 호스트 환경의 파일, 디렉터리를 이미지 안에 복사하는 경우 작성한다. | |
| ADD | “COPY”를 포함한다.
URL에 있는 파일을 붙여넣기 하는 것도 가능
또한 패키지, 압축파일의 경우에는 이를 해제하여 내용물만 붙여넣기 할 수 있다.
단, URL 상의 tar 파일 등은 해제되지 않은 상태에서 붙여넣기 된다. | |
| VOLUME | 이미지에 볼륨을 할당하고자 할 때 사용한다.
VOLUME /var/log
VOLUME [”/var/log”] : 컨테이너의 /var/log를 호스트에 있는 볼륨과 연결. 만약, 볼륨 이름을 지정한다면?
VOLUME testvol1:/var/log
ctn1이 testvol1과 연결
cnt2도 testvol1과 연결 되므로 좋지않음
만약, 컨테이너의 여러 디렉토리를 볼륨과 연결하고 싶다면
VOLUME /var/log /var/www/html /var/lib/mysql

VOLUME /var/log → 컨테이너의 /var/log를 호스트의 임의의 볼륨(ID)과 연결
VOLUME /var/www/html /root → 컨테이너의 두 디렉토리를 두 볼륨과 각각 연결 | |
| EXPOSE | 마치 방화벽에서 몇번 포트를 열 것인가를 지정하는 것
EXPOSE 80
EXPOSE 8080/udp
EXPOSE [”80”,”8080”] # 여러개의 포트 열기(EXPOSE 80 EXPOSE 8080 이렇게 두번 써도 됨)

docker run -p를 이용하여 호스트의 포트와 매핑해주면 외부에서 해당 포트로 접근이 가능해진다. | |
| ONBUILD | 이를 이용하여 베이스 이미지를 만들때에는 필요하지 않지만 생성된 이미지를 베이스이미지로 활용할 경우 사용되는 명령

ONBUILD ADD test.tar /usr/share/nginx/html/ → Dockerfile과 같은 위치에 test.tar는 없는 것
| |
| WORKDIR | 컨테이너 내에서 작업할 경로 설정
WORKDIR /var/www
[이 구간에서는 작업경로 /var/www]
WORKDIR /root
[이 이후부터는 작업경로 /root]
RUN cd /var/www는 내려가면 원래의 작업경로로 다시 돌아오기때문에 안됨 | |
| USER | 작업 사용자 지정하기 | |
| ARG | 컨테이너가 아닌 이미지에서 사용하는 변수 지정 | |
| ENV | 이미지에 시스템 환경변수 추가
USERNAME, PWD, SSH_CONNECTION
예를 들어 ENV A=”Hello”,면 컨테이너에서 “env” 명령을 실행하면 A=”hello”가 보인다. | |

CMD vs ENTRYPOINT

  • 둘다 Dockerfile 내에서 1번만 사용 (여러번 사용 시 마지막 라인만 처리)

예) test:1.0

FROM ubuntu

ENTRYPOINT [”top”] # top : cpu확인

CMD [”-d”,”10”] # -d 10 : 갱신주기 10

docker container run -it test:1.0

docker container run -it test:1.0 -d 2 : -d 2라는 명령을 전달, CMD가 겹치니까 -d 2를 선택함

CMD와 ENTRYPOINT에서 실행하는 명령어가 docker container run에서 실행하는 옵션과 동일한 경우 ENTRYPOINT는 모두 처리함. 하지만 CMD는 동일 옵션이 있는 경우 docker container run에 있는 옵션만을 처리한다.

ENTRYPOINT는 고정적으로 실행할 명령을 작성하고, CMD는 변경될 가능성이 있는 매개변수, 옵션 등에 대하여 지정할 때 주로 사용

만약, 컨테이너로 배포될 때 실행해야할 명령어가 ENTRYPOINT나 CMD 두개 가지고 너무 부족한 경우에는 쉘 파일을 만들고 CMD나 ENTRYPOINT를 이용해 해당 쉘을 실행하도록 설정한다.

ADD a.sh /root/a.sh

CMD [”/bin/bash”,”/root/a.sh”]

라고 하고 a.sh에 여러 명령어를 작성

COPY vs ADD

COPY test.tar /var/www/html : 압축파일 그대로 달라붙음

ADD test.tar /var/www/html : 압축파일을 풀어 내용물을 붙여넣음

또한

ADD website.tar.gz /var/www/html : 패키지를 묶고(tar) + 압축(gz)한 상태도 가능

ONBUILD 실습하기

”우리는 웹개발 팀장이다. 팀원들 중 /blog를 만드는 팀에게 아래와 같이 지시했다.”
제가 index.html 파일을 만들테니 blog팀은 개발된 파일, 디렉토리를 blog.tar로 만들어 build하세요
www.test.com/blog
www.test.com/shop

  • Dockerfile
FROM centos:7
RUN yum -y install httpd
EXPOSE 80
ADD index.html /var/www/html/index.html
ONBUILD ADD blog.tar /var/www/html

CMD httpd -D FOREGROUND
  • 팀장이 index.html 파일 만들어놓기
rapa@rapa:~/0818$ touch index.html
rapa@rapa:~/0818$ echo "<h2>TEAM MANAGER</h2>" > index.html
  • Dockerfile build
rapa@rapa:~/0818$ docker build -t webbase:1.0 .
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/6 : RUN yum -y install httpd
 ---> Running in c3810b6b99fa
Loaded plugins: fastestmirror, ovl
...
omplete!
Removing intermediate container c3810b6b99fa
 ---> e0256a5597cc
Step 3/6 : EXPOSE 80
 ---> Running in a5256cede49a
Removing intermediate container a5256cede49a
 ---> 18d3badf0e46
Step 4/6 : ADD index.html /var/www/html/index.html
 ---> a5b464356c83
Step 5/6 : ONBUILD ADD blog.tar /var/www/html
 ---> Running in 6b4d7a8003dc
Removing intermediate container 6b4d7a8003dc
 ---> 9aeba8ec1610
Step 6/6 : CMD httpd -D FOREGROUND
 ---> Running in b3afbd760a35
Removing intermediate container b3afbd760a35
 ---> ea572112d3ff
Successfully built ea572112d3ff
Successfully tagged webbase:1.0
  • 블로그 디렉토리에 blog.html 파일 만들기
  • blog아래 모든 파일들을 묶어 blog.tar 파일 만들기
rapa@rapa:~/0818$ mkdir blogdev
rapa@rapa:~/0818$ cd blogdev/
rapa@rapa:~/0818/blogdev$ mkdir blog
rapa@rapa:~/0818/blogdev$ pwd
/home/rapa/0818/blogdev
rapa@rapa:~/0818/blogdev$ touch blog/blog.html
rapa@rapa:~/0818/blogdev$ echo "<h2>BLOG TEAM MEMBER</h2>" > blog/blog.html 
rapa@rapa:~/0818/blogdev$ tar cf blog.tar blog/*
rapa@rapa:~/0818/blogdev$ ls
blog  blog.tar
  • Dockerfile 만들기 (blog)
  • 이때 ONBUILD 내용 해석
rapa@rapa:~/0818/blogdev$ touch Dockerfile
rapa@rapa:~/0818/blogdev$ vi Dockerfile
FROM webbase:1.0
  • build (이미지 생성)
rapa@rapa:~/0818/blogdev$ docker build -t webbase:blog .
Sending build context to Docker daemon  14.34kB
Step 1/1 : FROM webbase:1.0
# Executing 1 build trigger
 ---> e31708f56e98
Successfully built e31708f56e98
Successfully tagged webbase:blog
  • 이미지 확인
  • webbasee blog가 생겨있음
rapa@rapa:~/0818/blogdev$ docker image ls
REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
webbase             blog      e31708f56e98   37 seconds ago   418MB
webbase             1.0       ea572112d3ff   6 minutes ago    418MB
wordpress           latest    66b89e8b083b   2 weeks ago      609MB
dustndus8/mynginx   blue      b692a91e4e15   2 weeks ago      142MB
dustndus8/mynginx   green     b692a91e4e15   2 weeks ago      142MB
nginx               latest    b692a91e4e15   2 weeks ago      142MB
httpd               latest    f2a976f932ec   2 weeks ago      145MB
mysql               5.7       3147495b3a5c   3 weeks ago      431MB
centos              7         eeb6ee3f44bd   11 months ago    204MB
test                1.0       eeb6ee3f44bd   11 months ago    204MB
google/cadvisor     latest    eb1210707573   3 years ago      69.6MB
  • 컨테이너 동작시키기
rapa@rapa:~/0818/blogdev$ docker container run -d -p 8888:80 webbase:blog
e8525bdd95344e87610aca55cb9c8f2ec4a35271b10ad6fef9d3ad1dbd33e64b
  • :8888만 하면
  • 팀장이 만든 index 페이지 보임

  • :8888/blog/blog.html로 하면
  • blog 팀에서 만든 html 페이지 보임

즉, ONBUILD는 ONBUILD가 작성된 파일을 베이스 이미지로 하는 별도의 Dockerfile에서 동작하는 옵션이다.

QUIZ

ubuntu 18.04 이미지를 베이스 이미지로 하여 nginx를 설치하고, 해당 nginx에서는 개발자가 작성한 index.html 파일이 보이도록 설정한다. 외부에서 접속시 해당 컨테이너의 웹페이지가 보여야하며 포트번호는 8881을 이용하여 접속할 수 있어야 한다. 단, 위의 실습 전 각 ubuntu의 IP 주소는 192.168.1.1XX (114)로 설정해야 한다.

  1. IP 주소 바꾸기

NetworkAdapter VMnet0으로 변경

rapa@rapa:~$ sudo vi /etc/netplan/01-network-manager-all.yaml

yaml은 들여쓰기가 중요해 tab보다는 띄어쓰기로 사용 key: value (value앞에 띄워야함)

value가 한 개일 경우에는 바로 옆에 띄어쓰기 후 작성

value가 여러개인 경우

key :

  • value1

  • value2 리스트 형태로 작성 가능

# Let NetworkManager manage all devices on this system
network:
  ethernets:
    ens32:
      addresses: [192.168.1.114/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 168.126.63.1]
      dhcp4: no
  version: 2
# renderer: NetworkManagerrapa@rapa:~$ sudo netplan apply
rapa@rapa:~$ sudo netplan apply

ping을 통해 정상적으로 실행되는지 확인

웹서비스를 위한 컨테이너의 기본 홈 디렉토리

base image home dir

centos/ubuntu /var/www/html

httpd /usr/local/apache2/htdocs

nginx /usr/share/nginx/html

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get -y install nginx
EXPOSE 80
ADD index.html /var/www/html/index.html
CMD ["nginx","-g","daemon off;"]
rapa@rapa:~/0818$ docker build -t app:1.0 .
Sending build context to Docker daemon   16.9kB
Step 1/6 : FROM ubuntu:18.04
 ---> 8d5df41c547b
Step 2/6 : RUN apt-get update
rapa@rapa:~/0818$ docker run -it -d -p 8881:80 --name=app5 app:1.0
27f5ead8cde13868091f0cc22187183e89a1611346d9505625936ca214af2847

Quiz

다음의 조건을 활용하여 배포된 컨테이너는 접속 즉시 설치페이지에서 설치 후 게시판을 사용할 수 있어야 한다.

컨테이너는 2개가 필요하다.

이미지컨테이너
centos7을 베이스로 하여 xe:1.0 이미지를 만들어야 함xe 컨테이너 (xe01)
mysql 5.7db 컨테이너 (db01)

db는 3306이고 서로 컨테이너는 link로 연결되어야 함

xe01은 8888포트로 외부 연결 (192.168.1.1xx/xe → 설치페이지, db정보는 root pw는 test123, db이름은 xedb, db 호스트는 db01(링크된정보))

centos에 php 설치, php-fpm, php-gd, php-mysql 설치가 되어야하고 + 소스코드를 가져와서 풀어야 함

1. XE 이미지 만들기

Dockerfile

FROM centos:7
RUN yum clean all
RUN yum update -y
RUN yum -y install wget git httpd
RUN wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum -y localinstall remi-release-7.rpm
RUN yum -y install epel-release yum-utils
RUN yum-config-manager --enable remi-php74
RUN yum -y install php php-fpm php-gd php-mysql php-xml
RUN git clone https://github.com/xpressengine/xe-core.git /var/www/html/xe
WORKDIR /var/www/html/xe
RUN mkdir files
RUN chmod 707 -R files
WORKDIR /var/www/html
RUN chmod -R 707 xe
RUN chown -R apache:apache xe
EXPOSE 80
CMD httpd -D FOREGROUND
docker build -t xe:1.0 .

2. 컨테이너 배포

  • mysql:5.7을 이용해 root 패스워드를 test123으로 설정하고, 기본 db 이름도 지정하되 이름을 xe로 하여 컨테이너 배포. 컨테이너의 이름은 db1
rapa@rapa:~/0819/board$ docker container run -d --name db1 -e MYSQL_ROOT_PASSWORD=test123 -e MYSQL_DATABASE=xedb mysql:5.7
2ad475358f364d30a58f60b8935b3dc358e65c85cd421c0e5fc6d42fc8027424
  • xe:1.0 이미지를 이영하여 xe1 컨테이너를 생성하되, 위에서 만든 db1과 link 시키고 외부에는 8888포트를 컨테이너의 80번 포트로 매핑 시켜 배포
rapa@rapa:~/0819/board$ docker container run -d --name xe1 --link db1:mydb -p 8888:80 xe:1.0
49d85ce1cabee00181de540ac8cbba9bd01e8ecebca0a869aaad41538fa513da

3. http://211.183.3.X:8888/xe 접속

두 개의 컨테이너가 정상적을 배포되었다면 http://211.183.3.X:8888/xe로 접속하면 설치화면으로 들어가게 됩니다.

필요한 내용을 입력해 정상적인 게시판이 보이도록 함

0개의 댓글