Docker Hello World 프로그램 실습

만들려는 프로그램 개요

 

Mac OS에서 node.js 개발환경 구축하기 with VS Code

1. Mac OS에서 node.js 설치하기 맥북(Mac M2) Node.js 설치하기 homebrew1. Homebrew 사용하기Homebrew가 설치되어있다면, 터미널 앱을 다음 코드를 실행해서 쉽게 설치 할 수 있다.brew updatebrew install node 설치가

ourjune.tistory.com

 

Node.js로 에 Hello Docker!라는 스트링을 console.log 함수를 통해 출력

app.js라는 하나의 파일만 있음

커맨드라인에 "Hello Docker!"가 print되도록 하기!

 

실행방법 

node app.js

dockerfile을 만들어서 이미지로 빌드하고 테스트해보고 docke hub에 업로드

하고 다른 리눅스 서버에서 pull 받아서 컨테이너 위에서 실행

dockerfile에 node환경이 설정되어 있어야함

 

만약 docker 없이 실행한다면?

1. OS 설치

2. Node 설치

3. 코드 복사 (app.js)

4. 프로그램 실행 (node app.js)

위의 과정을 직접 설치하고 실행해야함.

 

Docker로 실행하기 위해서 위의 과정이 Dockerfile에 기술되어있어야함

 

Dockerfile의 생성

Docker에게 어떤 sw를 설치하고 실행할 지에 대한 명령을 텍스트로 기술해놓은 파일

먼저 베이스 이미지를 기술 FROM 키워드 사용

다음으로 코드 복사

마지막으로 코드 실행

FROM node:alpine
COPY . /app
WORKDIR /app
CMD node app.js

 

FROM node:alpine  node라는 sw에 alpine이라는 os 버전을 다운로드 받아라 OS 종류 적기. 예제에서는 경량 리눅스인 Alpine 선택 
COPY . /app 코드 복사 이미지에 포함이 될 코드 복사 .현재디렉토리에 정보를 /app (docker image안) 폴더 아래로 옮기기
WORKDIR /app Working directory를 지정 CMD 명령 전에 경로를 미리 선언해줘서 CMD 명령을 간단하게 해줌
CMD node app.js 실행하는 명령 앞에 지정 /app 폴더 아래에 위치한 app.js를 실행해라

 

<-> ENTRYPOINT

Container가 시작할 때 실행되어야 하는 명령어 지정하는데 사용 docker run

두개 동시에 사용 가능 ( ENTRYPOINT가 우선순위에 있음)

best practice는 CMD만 사용하는 !

둘다 dockerfile에서 여러번 실행되면 가장 마지막 것만 사용됨

두개 다 동일한 결과(CMD, ENTRYPOINT)

FROM debian:buster

COPY . /myproject
RUN apt-get update ...
CMD ["./cmd1.sh"]

FROM debian:buster

COPY . /myproject
RUN apt-get update ... =>docker build 명령 
CMD ["./cmd1.sh"]

 

docker run my-image라고 만들었음

./cmd1.sh가 기본으로 실행됨

 

CMD로 처음 지정한 명령은 overwrite이 가능 (기본 처음 실행 명령 이후 다른 스크립트를 지정하면서 컨테이너 런치할 때 바꿔치기 가능)

docker run my-image cmd2.sh 

라고 cmd2.sh를 별도 지정해주면 cmd2.sh 가 실행됨

 

ENTRYPOINT는 overwrite하기 위해서는 별도에 옵션 지정이 필요(--entrypoint)

FROM debian:buster

COPY . /myproject
RUN apt-get update ...
ENTRYPOINT ["entrypoint.sh"]
CMD ["param1", "param2"]

 

FROM debian:buster

COPY . /myproject
RUN apt-get update ...
ENTRYPOINT ["entrypoint.sh"]
CMD ["param1", "param2"]

 

docker run my-image

=> entrypoint.sh param1 param2 동시 사용하면 ENTRYPOINT가 기본 명령으로, CMD가 파라미터로(인자)로 제공됨

 

docker run my-image cmd2

=> entrypoint.sh cmd2 혼자 쓰이면 그 자체가 실행 명령, 같이 사용되는 지정된 명령의 따라다니는 파라미터로 . 파라미터가 따라다님 docker run하면서 바로 적용

 

docker run --entrypoint="/cmd3.sh" my-image

 

 

* 태그 포맷

FROM docker image 이름:버전정보(숫자 혹은 스트링)

(예. FROM python:3.7-slim-buster)

 

그외 Dockerfile 키워드

ARG

리눅스 환경변수 세팅, 빌드할 때 사용 가능, 최종 이미지에 저장되지 않음

ENV

리눅스 환경변수 세팅, 빌드할 때 사용 가능, 최종 이미지에 저장(컨테이너 실행(CMD, ENTRYPOINT)할 때도 사용가능)
USER

컨테이너를 실행할 때 사용할 유저 ID
EXPOSE

서비스 사용 포트 (예: mysql 서비스라면 3306, airflow 웹서비스라면 8080, EXPOSE 8080 3306)

RUN

이미지 빌드할 때 어느 커맨드를 실행할 건지 docker build(예. RUN apt-get update && apt-get install -y curl)

 

지금까지 배운 내용으로 Dockerfile이 만들어졌다면 이제 Docker Image 생성해야함

$ docker build --platfrom linux/amd64 

-t hello-world-docker .-t 태그 dockerfile의 이미지 이름을 지정, (버전을 같이 적어줄 수 있음). 은 현재경로 나타냄 -> path 정보

--platfrom 옵션 사용하면 완전히 os간의 호환성을 보장하지 못하기 때문에 리눅스 서버 위에 ARM 기반 아키텍처로 만들어지는 이미지는

범용적이지 않아서 일반 리눅스에서 안돌아감. 빌드를 할때 아키텍처를 미리 지정하기

 $ docker image ls  <- docker image가 잘 만들어졌는지 확인

tag를 따로 지정하지 않으면 latest가 디폴트로 부여됨

$ docker run hello-world-docker docker container로 실행

- docker run을 dockerfile에서 cmd 명령이 실행

- 이미지 버전이 여러개면 이미지 이름 버전 정보 같이

- cmd에 지정된 기본 명령이 실행됨

- entrypoint만 있었으면 entrypoint의 명령이 실행

- 둘다 있었으면 ~

- cmd 새로 쓴 sh 덮어쓰기...

만일 다른 컴퓨터에서 해당 이미지를 실행하고 싶으면? docker registry(docker hub)에 먼저 등록 필요

 

 

$ docker image ls

$ docker images

는 같은 명령어로 동일한 결과 확인 가능

시스템에 설치된 이미지 리스팅

repository tag imageId created size

namespace/imagename 버전정보,변형정보 

 

repository에 해당하는 값이 docker image 이름

- namespace나 accountid가 포함되어 있는 경우 도커 허브에서 다운로드 받은 이미지 (official이미지는 네임스페이스 없을 수도)

 

docker tag 별칭이지 이름을 바꾸는것이 아님(앞선 명령에서)

메인이미지의 특수한 정보(부가정보)(버전이나 변형) 를 나타냄 tag

유니크하게 identify하기 위해서 사용

image id는 유니크한 id

docker tag 로 별칭을 다시 줌? 첫번째 인자로 주어진 이미지에 두번째 인자로 별칭을 줌

이름을 두개 가짐 * 지난 수업때 내용 다시 확인 필요

docker image에서 : 뒤에 해당하는 값

 

포맷

repo이름/image이름:tag 

keeyong/hello-world-docker:latest

redis:13 -> 공식이미지일 경우 네임스페이스 없음 (DOCKER OFFICIAL IMAGE)

node:alpine -> 공식이미지일 경우 네임스페이스 없음 (DOCKER OFFICIAL IMAGE)

ubuntu:18.04 -> 공식이미지일 경우 네임스페이스 없음 (DOCKER OFFICIAL IMAGE)

 

 

% cat Dockerfile
FROM node:alpine
COPY . /app
WORKDIR /app
CMD node app.js
% ls -tl
total 16
-rw-r--r--  1 cookie  staff  58 11 18 17:42 Dockerfile
-rw-r--r--  1 cookie  staff  29 11 18 17:32 app.js
% cat app.js
console.log("Hello Docker!")
% node app.js
Hello Docker!

 

docker image ls

docker image rm -f <IMAGE ID>

% docker build --platform linux/amd64 -t hello-world-docker .
% docker run hello-world-docker
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Hello Docker!

% docker image ls
REPOSITORY                 TAG            IMAGE ID       CREATED         SIZE
hello-world-docker         latest         ae4e4a81028d   2 minutes ago   226MB

 

https://www.docker.com/products/docker-hub/

 

The World’s Largest Container Registry | Docker

Docker Hub is a container registry built for developers and open source contributors to find, use, and share their container images and access verified content.

www.docker.com

repository에 생성된 것 확인 후 다시 터미널로 돌아가서, 

% docker image ls
REPOSITORY                 TAG            IMAGE ID       CREATED          SIZE
hello-world-docker         latest         ae4e4a81028d   16 minutes ago   226MB

% docker tag hello-world-docker ourjune/hello-world-docker

% docker image ls
REPOSITORY                   TAG            IMAGE ID       CREATED          SIZE
ourjune/hello-world-docker   latest         ae4e4a81028d   35 minutes ago   226MB
hello-world-docker           latest         ae4e4a81028d   35 minutes ago   226MB
% docker login --username=ourjune
Password: 
Login Succeeded

 

+ ADD NEW INSTANCE

 

근데 이거 좀 많이 느리다 빡칠수도 ㅋㅋㅋ

$ docker version

$ docker pull ourjune/hello-world-docker

$ docker image ls

$ docker run ourjune/hello-world-docker

Hello Docker!