
html {
font-family: sans-serif;
}
body {
margin: 0;
}
section,
form {
padding: 1rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
margin: 2rem auto;
max-width: 40rem;
}
.form-control {
margin: 0.5rem 0;
}
input {
font: inherit;
}
input,
label {
display: block;
}
label {
font-weight: bold;
margin-bottom: 0.5rem;
}
button {
background-color: #2f005a;
border: 1px solid #2f005a;
color: white;
cursor: pointer;
padding: 0.5rem 1.5rem;
}
button:hover,
button:active {
background-color: #50005a;
border-color: #50005a;
}
FROM node
WORKDIR /app
COPY . /app
RUN npm install
EXPOSE 80
CMD [ "node", "server.js" ]
{
"name": "docker-complete",
"version": "1.0.0",
"description": "",
"main": "server.js",
"author": "Maximilian Schwarzmüller / Academind GmbH",
"license": "MIT",
"dependencies": {
"express": "^4.17.1",
"body-parser": "1.19.0"
}
}
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
let userGoal = 'Learn Docker!';
app.use(
bodyParser.urlencoded({
extended: false,
})
);
app.use(express.static('public'));
app.get('/', (req, res) => {
res.send(`
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<section>
<h2>My Course Goal</h2>
<h3>${userGoal}</h3>
</section>
<form action="/store-goal" method="POST">
<div class="form-control">
<label>Course Goal</label>
<input type="text" name="goal">
</div>
<button>Set Course Goal</button>
</form>
</body>
</html>
`);
});
app.post('/store-goal', (req, res) => {
const enteredGoal = req.body.goal;
console.log(enteredGoal);
userGoal = enteredGoal;
res.redirect('/');
});
app.listen(80);
이를 통해 다른 베이스 이미지에 여러분의 이미지를 구축할 수 있습니다. (노드 이미기 구축)
FROM node
WORKDIR /app
다음 단계로 도커에게 로컬 머신에 있는 파일이 이미지에 들어가야 하는지 알려야 합니다.
#COPY 명령을 사용합니다.
첫 번째 "." 이는 도커에게 기본적으로 Dockerfile이 포함된 동일한 폴더임을 알리는 겁니다.
(Dockerfile은 제외됩니다.)
두 번째 "." 은 그 파일을 저장해야 하는 이미지 내부의 경로입니다.
[ex] COPY . .
도커 컨테이너의 루트 엔트리를 사용하지 않고
서브 폴더를 사용하는 것이 좋습니다. 여기에서는 /app 이라고 지정.
COPY . /app
WORKDIR 을 사용한 경우 ./ 이 상대 경로는 /app을 나타냅니다.
COPY . ./ (파일이 복잡하면 보기 어려워 집니다.)
이제 Dockerfile과 동일한 폴더에 있는 모든 파일과 거기에 있는 모든 하위 폴더가
컨테이너 내부의 app 폴더에 복사됩니다.
노드 애플리케이션의 경우, 노드 애플리케이션의 모든 종속성을 설치하기 위해 npm install을 실행해야 했습니다.
모든 로컬 파일을 이미지에 복사한 후, 이미지에서 명령을 RUN하고 싶다고 알릴 수 있습니다. (이 경우 npm install)
RUN npm install
디폴트로 이러한 모든 명령은 도커 컨테이너 및 이미지의 작업 디렉토리에서 실행됩니다.
디폴트로 그 작업 디렉토리는, 컨테이너 파일 시스템의 루트 폴더입니다.
여기에서 코드를 app 폴더에 복사하고 있기 때문에, npm install도 app 폴더 내에서 실행하고 싶은데요.
도커에게 모든 명령이 그 폴더에서 실행되어야 한다고 알려주는 편리한 방법은
모든 것을 복사하기 전에 여기에서 이 명령을 설정하는 것입니다. WORKDIR 명령인데요. /app으로 설정하도록 하죠.
이것은 도커에게 모든 후속 명령이 그 폴더 내부에서 실행될 것임을 알리는 겁니다.
이미지는 컨테이너의 템플릿이어야 함을 명심하세요.
이미지를 실행 하는 것이 아니라, 이미지를 기반으로 컨테이너를 실행하는 겁니다.
RUN, CMD 차이점: CMD 는 이미지가 생성될 때 실행되지 않고, 이미지를 기반으로 컨테이너가 시작될 때 실행됨.
CMD의 경우, 구문이 약간 다릅니다. 여기서 우리는 배열을 전달합니다. 명령을 두 개의 문자열로 분할하는데요.
도커에게 이미지를 기반으로 컨테이너가 생성될 때마다 그 컨테이너 내부에 있는 node 명령을 사용하여 server.js 파일을 실행하도록 지시.
EXPOSE 80
CMD [ "node", "server.js" ]
(CMD에 특정하지 않으면 베이스 이미지가 실행되며, 그게 없는 경우 에러가 발생합니다.)
이 노드 웹 서버는 포트 80에서 수신 대기하게 됩니다. (이기 까지 도커 컨테이너가 격리되어 있음)
컨테이너 내부의 노드 애플리케이션에서 포트 80을 수신할 때, 컨테이너는 그 포트를 우리의 로컬 머신에 노출하진 않습니다.
따라서 컨테이너 내부에서만 무언가를 수신 대기 중이기 때문에, 그 포트에서 수신할 수 없는 거죠.
언제나 Dockerfile의 마지막 명령 전에 이 컨테이너가 시작될 때 로컬 시스템에 특정 포트를 노출하고 싶다는 것을 도커에 알리는 EXPOSE 80 명령을 추가해야 합니다.
Dockerfile에 이 EXPOSE 80 명령이 있지만 실제론 이 명령은 도큐먼테이션 목적으로만 추가되었을 뿐이라는 겁니다. 즉 아무것도 하지 않습니다. (그래도 추가하는 것을 권장합니다.)
우리가 해야 할 일은 이 컨테이너를 실행할 때 여기에 플래그를 추가하는 겁니다. 이미지 이름 앞의 -p 플래그를 넣는데요. 이는 publish를 나타냅니다. 이를 통해 도커에게 어떤 로컬 포트가 있는지 알려줄 수 있습니다.
-p 다음 애플리케이션에 액세스하려는 로컬 포트를 지정합니다.
이 경우엔 예를 들어 3000이라고 하죠. 그런 다음 : 넣고, 내부 도커 컨테이너 노출 포트를 넣습니다. (이 경우 80 입니다.)