📌 도커 이미지란?
- Docker 이미지는 애플리케이션과 그 실행에 필요한 모든 파일, 라이브러리, 환경 설정, 종속성 등을 포함한 읽기 전용 템플릿을 말함.
- 이 이미지는 컨테이너를 실행하기 위한 청사진 역할을 하며, 여러 번 재사용할 수 있음.
- 도커 이미지는 계층 구조로 구성되어 있으며, 각각의 계층은 하나의 파일 시스템 변경 사항을 나타냄.
Dockerfile - 도커이미지를 만들기 위한 명세포
명세표 - 주문하는 사람의 바람이 담겨있음
실습
FROM: 베이스이미지를 지정
-> 맨 위에 써줘야 함
FROM nginx:latest
- 베이스 이미지
- from이란 시작점을 의미하는데, Dockerfile에서 FROM은 이걸 바탕으로 시작한다는 의미임
- nginx는 이건 이미지의 이름임. 이미지는 운영체제 + 프로그램 + 설정을 하나로 묶은 덩어리임, 웹서버를 위한 프로그램으로 인터넷에서 웹 페이지를 보여주는 일을 하는 소프트웨어임
- latest는 최신 버전의 nginx 웹 서버를 가져온다는 의미
root@host:~# mkdir /docker
root@host:~# cd /dockerroot@host:/docker# vi Dockerfile

root@host:/docker# docker build -t mynginx:1 .
docker build: 이미지를 만들겠다는 의미임.
-t mynginx:1: 이미지 이름과 버전을 설정하는 옵션임
뒤에 붙은 :1은 내가 만든 파일 버전 번호임, 앞으로 추가로 더 만들 때 숫자만 바꿔주면 됨
-t: tag
. : 현재 디렉터리

- # 베이스 이미지라는 주석을 같은 줄에 남기면 안 되고, 다음 줄에 작성해야 됨.
- 안 그러면 위와 같은 error가 발생함.


root@host:/docker# docker image ls

root@host:/docker# docker rm -f $(docker ps -qa)
3f5f5d42ce3a
9f34d840b4da
84275b56ac90
2e4b8f2033da
2084946d521f
ae1a73192613
- 이미지의 이름은 다르지만 모든 레이어가 동일하기 때문에 이미지를 참조하고 있음.
root@host:/docker# docker run -dp 8080:80 --name myweb mynginx:1

docker run: 컨테이너를 실행하는 명령어
-> 이미지에서 실제로 실행되는 프로그램을 만들겠다는 의미
-> 아까 만들었던 mynginx:1을 실행 시키겠다는 의미임
-d: 백그라운드 실행
-> detached mode의 약자임
-> 백그라운드에서 실행하겠다는 뜻임 = 명령어를 실행하고 나서 터미널을 다른 작업을 할 수 있도록 그대로 두고 컨테이너를 실행시키겠다는 의미임
p 8080:80: 포트 매핑
- 외부에서 컨테이너에 접근할 수 있는 포트를 설정한 것
- 8080은 호스트 머신의 8080포트임. 즉, localhost:8080 하면 됨
- 80은 컨테이너 내에서 실행되는 애플리케이션 포트임. 이 부분은 mynginx:1 이미지 안의 웹 서버가 실행되는 포트임/ 그러니까 엔지넥스나 http는 80번으로 열림, 컨테이너 안에서 80번으로 열린다는 의미임
root@host:/docker# curl localhost:8080

- 만약에 curl이 안된다면 systemctl restart docker 실행
WORKDIR: 디렉터리 지정
-> 재지정전까지 영구적으로 유지
-> cd 대신 사용하면 됨. 되도록이면 cd를 안 쓰는 게 좋음
-> 컨테이너에 접속했을 때 존재하는 디렉터리가 마지막으로 지정한 WORKDIR이 됨.


pwd
- Dockefile의 마지막 WORKDIR
FROM nginx:latest
# 베이스 이미지
WORKDIR /usr/share/nginx/html
#작업디렉터리 변경
root@host:/docker# docker build -t mynginx:2
-> 현재 디렉터리의 Dockerfile을 토대로 mynginx:2라는 이미지를 만들어라.

root@host:/docker# docker build -t mynginx:2.
root@host:/docker# docker run -dp 8082:80 --name myweb2 mynginx:2

- 이미지를 생성하면서 a라는 디렉터리에서 a-1 작업 후에 b디렉터리에서 b-1 작업을 해야 함. cd로 이동을 하는 게 아니라 WORKDIR a 한 후 a-1 작업을 끝내고 다시 WORKDIR b 후에 b-1 작업을 하면 됨.
COPY: 호스트의 파일이나 폴더를 컨테이너 이미지에 삽입

root@host:/docker# echo copy_test > index.html
root@host:/docker# docker build -t mynginx:3 .
root@host:/docker# docker run -dp 8083:80 --name myweb3 mynginx:3


-> WORKDIR에 index.html이 잘 복사된 걸 확인 가능함.
COPY <호스트파일> <컨테이너파일>
COPY <호스트경로> <컨테이너경로>
- 파일은 파일로, 폴더는 폴더로 하면 실수할 여지가 줄어든다.

- 이번에는 경로 복사

root@host:/docker# vi Dockerfile
root@host:/docker# docker build -t mynginx:4 .
root@host:/docker# docker run -dp 8084:80 --name myweb4 mynginx:4
root@host:/docker# docker exec myweb4 ls
50x.html
Dockerfile
index.html
ADD: 웹상에 존재하는 파일도 가져올 수 있고, tar로 압축된 파일은 압축이 자동해제
-> Dockerfile에서 파일을 복사하는 명령어임. 이 명령어는 호스트 시스템에서 Docker이미지로 파일을 추가할 때 사용됨.
COPY와 비슷, 되도록이면 COPY를 쓰자
root@host:/docker# tar -cvf test.tar index.html
-c: 압축파일 생성
v: 과정 출력
f: 파일 test.tar
root@host:/docker# vi Dockerfile

- ADD: 파일을 추가하는 작업을 수행함
- test.tar .: 호스트 컴퓨터에 있는 파일 또는 디렉토리임.
-> 여기서는 test.tar라는 tar 압축 파일을 Docker이미지로 복사하고 있음. 이 파일은 현재 디렉토리에 있어야 함
root@host:/docker# docker run -dp 8085:80 --name myweb5 mynginx:5
root@host:/docker# curl localhost:8085
copy_test
- 압축이 해제되어 index.html 파일이 잘 보이는 걸 확인 가능함
ADD이랑 COPY의 차이점
-> ADD는 자동으로 압축 해제하거나 URL을 통해 파일을 다운로드 할 수 있음
-> 하지만 COPY는 단순히 파일을 복사만 함. 압축 파일을 해제하거나 URL에서 다운로드하지 않음
RUN: 컨테이너 이미지 빌드 단계에서 수행되는 명령

- RUN명령으로 cd/ usr/share/nginx/html을 수행했지만, 결론적으로는 그다음 레이어의 COPY라는 명령을 수행할 때는 RUN 레이어의 수행결과가 반영되지 않음. 왜냐하면 레이어끼리는 서로 독립적이기 때문임.
root@host:/docker# docker run -dp 8086:80 --name myweb6 mynginx:6
root@host:/docker# docker exec -it myweb6 bash
root@36e608450499:/# cat index.html
copy_test
root@36e608450499:/# cat /usr/share/nginx/html/index.html

어떤 명령을 여러 개 수행하고 싶다면 &&으로 묶어서 길게 써서 사용하자.
RUN <명령어 1> && <명령어 2> && <명령어 3>...
ex) RUN apt update -y && apt install -y <패키지 2> && systemctl restart <패키지>
실습) FROM, RUN , WORKDIR 명령을 활용하여 댕댕이 템플릿을 포함하는 도커이미지를 myhttpd:1 이라는 이미지를 생성해서 테스트해 보세요. 베이스이미지는 httpd:latest로 하고, 이 이미지로 컨테이너를 띄웠을 때 211.183.3.100:9090 을 쳤을 때 웹페이지가 뜨도록 해보세요.
mkdir copy
cd /copy
root@host:/docker/copy # wget https://www.free-css.com/assets/files/free-css-templates/download/page296/neogym.zip
root@host:/docker/copy# unzip neogym.zip
root@host:/docker/copy# mv neogym yum

root@host:/docker/copy# mv neogym-html yum
root@host:/docker/copy# vi Dockerfile

root@host:/docker/copy# docker build -t myhttpd:1 .
root@host:/docker/copy# docker run -dp 9090:80 --name yum myhttpd:1

CMD: 컨테이너가 실행되는 단계에서 수행할 명령
- 컨테이너를 생성 및 실행했을 때 컨테이너 내부에서 프로세스가 포어그라운드로 잘 동작하도록 하는 명령
- 보통은 맨 마지막에 한번 적어줌
root@host:/docker/copy# docker inspect yum

vi Dockerfile

- httpd 컨테이너: httpd -D FOREGROUND
-> CMD형태로 표현하면 됨
CMD
-> Dockerfile에서 컨테이너가 시작될 때 실행할 명령어
-> Apache 서버의 옵션임. 이 옵션은 Apache를 특정 모드로 실행할 때 사용됨.
-> FOREGROUND: Apache 서버를 백그라운드가 아닌 포그라운드에서 실행하겠다는 의미임. 컨테이너에서는 포그라운드로 실행해야만 계속 실행 상태를 유지하면서 로그를 볼 수 있음.
root@host:/docker/copy# cd ..
root@host:/docker# mkdir cmd
root@host:/docker# cd cmd
root@host:/docker/cmd# vi Dockerfile

root@host:/docker/cmd# docker build -t cent:1 .
root@host:/docker/cmd# docker run -d --name sleep cent:1

- 억지로 컨테이너 내부의 포어그라운드 프로세스를 만들어줌

ENTRYPOINT ["sleep"]
-> Dokerfile에서 컨테이너가 실행될 때 실행되는 명령어
-> 컨테이너가 시작될 때 반드시 실행되어야 하는 명령어
-> CMD랑 다르게 ENTRYPOINT는 다른 명령어를 지정해도 고정된 명령어로 실행됨
root@host:/docker/cmd# docker rm -f $(docker ps -qa)
# 삭제
root@host:/docker/cmd# docker build -t entry:1 .
root@host:/docker/cmd# docker run -dp 5959:80 --name etest entry:1

# CMD와 크게 다른게 없어 보

- sleep infinity test라는 명령으로는 컨테이너가 포어그라운드가 될 수 없음

root@host:/docker/cmd# docker build -t entry:2 .
root@host:/docker/cmd# docker run -dp 5952:80 --name etest2 entry:2 120


- CMD는 결국 Dockerfile에서도 지정 가능하고 컨테이너를 실행할 때도 이미지 오른쪽에 넣어줄 수 있음. 결국 컨테이너를 실행하면서 CMD를 적어주면 Dockerfile에서 작성했었던 CMD는 무시됨.
실습) ubuntu:latest를 베이스이미지로 하여 컨테이너를 띄웠을 때 간단한 웹페이지가 뜨는 myubun:1 이라는 컨테이너이미지를 만들어 보세요.
root@host:/docker/myubun# docker run -it --name ubun ubuntu:latest bash
- 컨테이너는 기본적으로 root사용자가 아님
root@c8220f389059:/# apt update -y
- 컨테이너가 구닥다리니까 먼저 update를 해야 됨
root@c8220f389059:/# apt install -y nginx
root@7a6c9030ddd2:/# nginx -g 'daemon off;'
# 업데이트, 설치, nginx동작 => 우리가 도커파일로 작성해야 하는 내용.
vi Dockerfile
FROM ubuntu:latest
RUN apt update -y && apt install -y nginx
CMD ["nginx","-g","daemon off;"]
root@host:/docker/cmd# docker build -t myubun:1 .
root@host:/docker/cmd# docker run -dp 5656:80 --name web myubun:1


root@host:/docker/cmd# docker image prune -fa
# 이미지 전체 삭제
EXPOSE : 포트를 노출. 사실상 의미 없음.
- docker run을 통해 컨테이너 생성할 때 -P(대문자 P)의 경우엔 호스트의 포트를 랜덤 하게 부여할 수 있음
- 이때 컨테이너의 포트는 EXPOSE 된 포트가 명시됨
- -p 옵션을 사용할 때만 유용한 명령어다. -p(publish) 할 때는 의미 없음.
root@host:/docker/cmd# cd ..
root@host:/docker# mkdir expose
root@host:/docker# cd expose/
root@host:/docker/expose# vi Dockerfile
FROM nginx:latest
EXPOSE 80
root@host:/docker/expose# docker build -t expose:1 .
root@host:/docker/expose# docker run -dP --name exptest expose:1
- 대문자 dP
ENV : 환경변수 선언
vi Dockerfile

root@host:/docker/expose# docker run -it --name env envtest:1 bash
root@9d969dcc6290:/# echo $ENVTEST

Dockerfile 작성법
- 컨테이너 레지스트리(Registry, 저장소)
- 레지스트리 = 도서관. 레포지스토리 = 책장, 태그 = 책(버전별로)
- 다양한 레지스트리가 존재함
도커 허브 = 퍼블릭한 레지스트리
- 클라우드는 기본적으로 AWS ECR, GCP GCR, Azure ACR 같은 프라이빗 및 퍼블릭 레지스트리 서비스를 제공함, 내가 Harbor나 Nexus 같은 사설 레지스트리를 직접 구축할 수도 있음.

도커이미지를 레지스트리에 올리려면
1. 애초에 docker build를 레지스트리 주소로 만들면 됨
2. 기존의 이미지를 올리고 싶으면, 기존 이미지를 docker tag라는 명령으로 새로 만들어 주면 됨
root@host:/docker# vi Dockerfile
FROM nginx:latest
root@host:/docker# docker build -t oolralra/myweb:1.

root@host:/docker# docker tag myweb:1 choyunji/myweb:2
- 만약, 기존 이미지를 레지스트리에 올리고 싶다면 tag명령으로 새로운 태그를 만들면 됨

- image가 잘 생성된 걸 볼 수 있음
이제 도커에 로그인해 보자
root@host:/docker# docker login -u choyunji



실습) ubuntu:latest를 베이스이미지로 하여 tomcat을 설치하고 index.jsp를 통해 컨테이너의 아이피를 보여주는 간단한 파일을 배포하는 이미지를 만든 후 도커 허브에 push 해서 테스트해보세요. 레포이름은 tom, 태그는 81
curl localhost:8989 를 쳤을 때 index.jsp 파일이 보이면 됩니다.
root@host:/docker# mkdir tomcat_docker
root@host:/docker# cd tomcat_docker/
root@host:/docker/tomcat_docker# vi Dockerfile
root@host:/docker/tomcat_docker# docker build -t tom:81 .
root@host:/docker/tomcat_docker# docker run -d -p 8989:8080 --name tomcat81 tom:81

FROM ubuntu:latest
RUN apt-get update && apt-get install -y openjdk-11-jdk wget && wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.100/bin/apache-tomcat-9.0.100.tar.gz && tar -xvzf apache-tomcat-9.0.100.tar.gz && mv apache-tomcat-9.0.100 /opt/tomcat
EXPOSE 8989
RUN echo '<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>' > /opt/tomcat/webapps/ROOT/index.jsp && \
echo 'hello world' >> /opt/tomcat/webapps/ROOT/index.jsp
CMD ["/opt/tomcat/bin/catalina.sh", "run"]
root@host:/docker/tomcat_docker# curl http://localhost:8989

root@host:/docker/tomcat_docker# docker build -t choyunji/tomcat81:1 .

root@host:/docker/tomcat_docker# docker push choyunji/tomcat81:1
-> 먼저 이미지가 잘 동작하는지 docker run을 통해 테스트 후에 push를 하는게 좋


강사님 풀이
1. 필요한 패키지 설치 -ubuntu에서는 update 후에 openjdk-11-jdk unzip wget
2. 압축해제 후 , tomcat 디렉터리 이름 변경 후 권한 부여
3. 호스트에 미리 만들어 놓은 index.jsp파일도 넣어주고
4. tomcat을 foreground로 동작시키기 위한 CMD 구성
root@host:/docker/tom# docker run -it --name tomcat ubuntu:latest bash
- 들어가서 각 명령이 잘 먹히는지 확인
root@379a9ca335a3:/# apt update -y
root@379a9ca335a3:/# apt install -y openjdk-11-jdk unzip wget
wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.39/bin/apache-tomcat-10.1.39.zip
root@379a9ca335a3:/# unzip apache-tomcat-10.1.39.zip
root@379a9ca335a3:/# mv apache-tomcat-10.1.39 tomcat
root@379a9ca335a3:/# rm -rf apache-tomcat-10.1.39.zip
root@379a9ca335a3:/# chmod 777 -R tomcat
root@379a9ca335a3:/# ./tomcat/bin/catalina.sh run
- 창을 하나 더 열어서

- 컨테이너 IP조회후 접속 => tomcat 이 잘 동작하는걸 확인.
도커 이미지 지울 때
docker rmi choyunji/tom:1
'AWS Cloud School 8기 > 도커(docker)' 카테고리의 다른 글
디스크 용량 확장/ mysql 컨테이너 생성/--link 옵션/ 사설저장소(private registry) (1) | 2025.04.02 |
---|---|
Docker Swarm (1) | 2025.04.01 |
docker compose/ 자동 재시작 스크립트/ 2번 기본 vim 편집기 (0) | 2025.03.30 |
다양한 앱 배포/ 웹 어플리케이션/ 프레임워크/ sudo lsof -i :<포트 번호>/ sudo kill -9 <PID>/ (0) | 2025.03.30 |
컨테이너 가상화 (6) | 2025.03.18 |