Docker로 Node.js 애플리케이션을 구축하는 방법
소개
Docker 플랫폼을 사용하면 개발자가 애플리케이션을 컨테이너로 패키징하고 실행할 수 있습니다. 컨테이너는 공유 운영 체제에서 실행되는 격리된 프로세스로, 가상 머신에 대한 더 가벼운 대안을 제공합니다. 컨테이너가 새로운 것은 아니지만 더 많은 개발자가 분산 애플리케이션 아키텍처를 사용함에 따라 프로세스 격리 및 환경 표준화를 비롯한 여러 가지 이점을 제공합니다.
Docker를 사용하여 애플리케이션을 빌드하고 확장할 때 출발점은 일반적으로 애플리케이션용 이미지를 생성한 다음 컨테이너에서 실행할 수 있습니다. 이미지에는 애플리케이션 코드, 라이브러리, 구성 파일, 환경 변수 및 런타임이 포함됩니다. 이미지를 사용하면 컨테이너의 환경이 표준화되고 애플리케이션을 빌드하고 실행하는 데 필요한 항목만 포함됩니다.
이 자습서에서는 나중에 사용할 수 있도록 Docker 허브를 사용하는 정적 웹 사이트에 대한 애플리케이션 이미지를 만듭니다. 마지막으로 Docker Hub 리포지토리에서 저장된 이미지를 가져오고 다른 컨테이너를 빌드하여 애플리케이션을 다시 만들고 확장하는 방법을 보여줍니다.
전제 조건
이 자습서를 따르려면 다음이 필요합니다.
- Ubuntu 18.04 서버 1개, 이 초기 서버 설정 가이드에 따라 설정
- Ubuntu 18.04에서 Docker를 설치하고 사용하는 방법의 1단계와 2단계에 따라 서버에 Docker를 설치했습니다.
- NodeSource에서 관리하는 PPA로 설치하는 지침에 따라 Node.js 및 npm이 설치되었습니다.
- Docker 허브 계정. 이를 설정하는 방법에 대한 개요는 Docker Hub 시작하기 소개를 참조하세요.
1단계 - 애플리케이션 종속성 설치
이미지를 만들려면 먼저 애플리케이션 파일을 만든 다음 컨테이너에 복사해야 합니다. 이러한 파일에는 애플리케이션의 정적 콘텐츠, 코드 및 종속성이 포함됩니다.
루트가 아닌 사용자의 홈 디렉터리에 프로젝트 디렉터리를 만듭니다. 이 예제의 디렉터리 이름은 node_project
이지만 다른 것으로 자유롭게 교체할 수 있습니다.
- mkdir node_project
다음 디렉터리로 이동합니다.
- cd node_project
이것은 프로젝트의 루트 디렉토리가 됩니다.
다음으로 프로젝트의 종속성 및 기타 식별 정보가 포함된 package.json
파일을 만듭니다. nano
또는 선호하는 편집기로 파일을 엽니다.
- nano package.json
이름, 작성자, 라이선스, 진입점 및 종속성을 포함하여 프로젝트에 대한 다음 정보를 추가합니다. 작성자 정보를 자신의 이름과 연락처 세부 정보로 바꾸십시오.
{
"name": "nodejs-image-demo",
"version": "1.0.0",
"description": "nodejs image demo",
"author": "Sammy the Shark <sammy@example.com>",
"license": "MIT",
"main": "app.js",
"keywords": [
"nodejs",
"bootstrap",
"express"
],
"dependencies": {
"express": "^4.16.4"
}
}
이 파일에는 공유되는 프로젝트 이름, 작성자 및 라이센스가 포함됩니다. 라이센스 필드에 npm MIT 라이센스를 부여하여 애플리케이션 코드의 무료 사용 및 배포를 허용합니다.
또한 파일은 다음을 지정합니다.
\main\
: 애플리케이션app.js
의 진입점입니다. 다음에 이 파일을 생성합니다.\dependencies\
: 프로젝트 종속성 — 이 경우 Express 4.16.4 이상입니다.
이 파일은 리포지토리를 나열하지 않지만 package.json
파일에 리포지토리를 추가하는 지침에 따라 리포지토리를 추가할 수 있습니다. 이것은 응용 프로그램의 버전을 관리하는 경우 좋은 추가 기능입니다.
CTRL + X
를 입력하여 파일을 저장하고 닫습니다. Y
를 누른 다음 ENTER
를 눌러 변경 사항을 확인합니다.
프로젝트의 종속성을 설치하려면 다음 명령을 실행하십시오.
- npm install
이렇게 하면 프로젝트 디렉터리의 package.json
파일에 나열된 패키지가 설치됩니다.
이제 애플리케이션 파일 빌드로 이동할 수 있습니다.
2단계 - 애플리케이션 파일 생성
사용자에게 상어에 대한 정보를 제공하는 웹사이트를 만들 것입니다. 이 애플리케이션에는 기본 진입점인 app.js
와 프로젝트의 정적 자산을 포함할 views
디렉토리가 있습니다. 랜딩 페이지인 index.html
은 사용자에게 몇 가지 예비 정보와 더 자세한 상어 정보가 있는 페이지 sharks.html
에 대한 링크를 제공합니다. views
디렉토리에서 랜딩 페이지와 sharks.html
을 모두 생성합니다.
먼저 기본 프로젝트 디렉토리에서 app.js
를 열어 프로젝트 경로를 정의합니다.
- nano app.js
이 파일의 첫 번째 부분에서 Express 애플리케이션 및 라우터 개체를 만들고 기본 디렉터리 및 포트를 상수로 정의합니다.
const express = require('express');
const app = express();
const router = express.Router();
const path = __dirname + '/views/';
const port = 8080;
require
함수는 app
및 router
객체를 생성하는 데 사용되는 express
모듈을 로드합니다. router
개체는 응용 프로그램의 라우팅 기능을 수행하며 HTTP 메서드 경로를 정의할 때 이 개체에 추가하여 응용 프로그램이 요청을 처리하는 방법을 정의합니다.
파일의 이 섹션은 path
및 port
와 같은 몇 가지 상수도 설정합니다.
path
: 현재 프로젝트 디렉토리 내의views
하위 디렉토리가 될 기본 디렉토리를 정의합니다.port
: 포트8080
에서 수신 대기하고 바인딩하도록 앱에 지시합니다.
다음으로 router
개체를 사용하여 애플리케이션의 경로를 설정합니다.
...
router.use(function (req,res,next) {
console.log('/' + req.method);
next();
});
router.get('/', function(req,res){
res.sendFile(path + 'index.html');
});
router.get('/sharks', function(req,res){
res.sendFile(path + 'sharks.html');
});
router.use
함수는 라우터의 요청을 기록하고 애플리케이션의 경로로 전달하는 미들웨어 함수를 로드합니다. 이는 기본 프로젝트 URL에 대한 GET
요청이 index.html
페이지를 반환하고 GET
페이지를 반환하도록 지정하는 후속 함수에서 정의됩니다. > /sharks
경로에 대한 요청은 sharks.html
을 반환해야 합니다.
마지막으로 router
미들웨어와 애플리케이션의 정적 자산을 마운트하고 포트 8080
에서 수신 대기하도록 앱에 지시합니다.
...
app.use(express.static(path));
app.use('/', router);
app.listen(port, function () {
console.log('Example app listening on port 8080!')
})
완성된 app.js
파일에는 다음 코드 줄이 모두 포함되어 있습니다.
const express = require('express');
const app = express();
const router = express.Router();
const path = __dirname + '/views/';
const port = 8080;
router.use(function (req,res,next) {
console.log('/' + req.method);
next();
});
router.get('/', function(req,res){
res.sendFile(path + 'index.html');
});
router.get('/sharks', function(req,res){
res.sendFile(path + 'sharks.html');
});
app.use(express.static(path));
app.use('/', router);
app.listen(port, function () {
console.log('Example app listening on port 8080!')
})
완료되면 파일을 저장하고 닫습니다.
다음으로 일부 정적 콘텐츠를 애플리케이션에 추가합니다. views
디렉터리를 생성하여 시작합니다.
- mkdir views
방문 페이지 파일인 index.html
을 엽니다.
- nano views/index.html
다음 코드를 파일에 추가하면 Boostrap을 가져오고 더 자세한 sharks.html
정보 페이지에 대한 링크가 있는 jumbotron 구성 요소가 생성됩니다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>About Sharks</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
<div class="container">
<button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
</button> <a class="navbar-brand" href="#">Everything Sharks</a>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav mr-auto">
<li class="active nav-item"><a href="/" class="nav-link">Home</a>
</li>
<li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<h1>Want to Learn About Sharks?</h1>
<p>Are you ready to learn about sharks?</p>
<br>
<p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a>
</p>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6">
<h3>Not all sharks are alike</h3>
<p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.
</p>
</div>
<div class="col-lg-6">
<h3>Sharks are ancient</h3>
<p>There is evidence to suggest that sharks lived up to 400 million years ago.
</p>
</div>
</div>
</div>
</body>
</html>
다음은 index.html
파일의 다양한 요소에 대한 빠른 분석입니다. 최상위 탐색 모음을 통해 사용자는 홈 페이지와 Sharks 페이지 사이를 전환할 수 있습니다. navbar-nav
하위 구성 요소에서 Bootstrap의 active
클래스를 사용하여 사용자에게 현재 페이지를 나타냅니다. 또한 app.js
에서 정의한 경로와 일치하는 정적 페이지에 대한 경로를 지정했습니다.
...
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav mr-auto">
<li class="active nav-item"><a href="/" class="nav-link">Home</a>
</li>
<li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a>
</li>
</ul>
</div>
...
또한 점보트론 버튼에 상어 정보 페이지 링크를 만들었습니다.
...
<div class="jumbotron">
<div class="container">
<h1>Want to Learn About Sharks?</h1>
<p>Are you ready to learn about sharks?</p>
<br>
<p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a>
</p>
</div>
</div>
...
헤더에 사용자 지정 스타일 시트에 대한 링크도 있습니다.
...
<link href="css/styles.css" rel="stylesheet">
...
이 단계의 끝에서 이 스타일 시트를 생성합니다.
완료되면 파일을 저장하고 닫습니다.
애플리케이션 랜딩 페이지가 준비되면 상어 정보 페이지인 sharks.html
을 생성하여 관심 있는 사용자에게 상어에 대한 자세한 정보를 제공할 수 있습니다.
파일 열기:
- nano views/sharks.html
Bootstrap, 사용자 지정 스타일 시트 및 특정 상어에 대한 자세한 정보를 가져오는 다음 코드를 추가합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>About Sharks</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="css/styles.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
</head>
<nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
<div class="container">
<button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
</button> <a class="navbar-brand" href="/">Everything Sharks</a>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav mr-auto">
<li class="nav-item"><a href="/" class="nav-link">Home</a>
</li>
<li class="active nav-item"><a href="/sharks" class="nav-link">Sharks</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron text-center">
<h1>Shark Info</h1>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6">
<p>
<div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
</div>
<img src="https://assets.linux-console.net/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
</p>
</div>
<div class="col-lg-6">
<p>
<div class="caption">Other sharks are known to be friendly and welcoming!</div>
<img src="https://assets.linux-console.net/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
</p>
</div>
</div>
</div>
</html>
이 파일에서 다시 한 번 active
Bootstrap 클래스를 사용하여 현재 페이지를 나타냅니다.
완료되면 파일을 저장하고 닫습니다.
마지막으로 css
폴더를 생성하여 index.html
및 sharks.html
에 연결한 사용자 정의 CSS 스타일 시트를 생성합니다. 뷰
디렉토리:
- mkdir views/css
스타일 시트를 엽니다.
- nano views/css/styles.css
페이지에 원하는 색상과 글꼴을 설정하는 다음 코드를 추가합니다.
.navbar {
margin-bottom: 0;
}
body {
background: #020A1B;
color: #ffffff;
font-family: 'Merriweather', sans-serif;
}
h1,
h2 {
font-weight: bold;
}
p {
font-size: 16px;
color: #ffffff;
}
.jumbotron {
background: #0048CD;
color: white;
text-align: center;
}
.jumbotron p {
color: white;
font-size: 26px;
}
.btn-primary {
color: #fff;
text-color: #000000;
border-color: white;
margin-bottom: 5px;
}
img,
video,
audio {
margin-top: 20px;
max-width: 80%;
}
div.caption: {
float: left;
clear: both;
}
글꼴 및 색상 설정 외에도 이 파일은 최대 너비
를 80%로 지정하여 이미지 크기를 제한합니다. 이렇게 하면 사진이 페이지에서 원하는 것보다 더 많은 공간을 차지하는 것을 방지할 수 있습니다.
완료되면 파일을 저장하고 닫습니다.
애플리케이션 파일이 준비되고 프로젝트 종속 항목이 설치되면 애플리케이션을 시작할 준비가 된 것입니다.
필수 구성 요소의 초기 서버 설정 자습서를 따랐다면 SSH 트래픽만 허용하는 활성 방화벽을 갖게 됩니다. 포트 8080
에 대한 트래픽을 허용하려면 다음을 실행하십시오.
- sudo ufw allow 8080
애플리케이션을 시작하려면 프로젝트의 루트 디렉토리에 있는지 확인하십시오.
- cd ~/node_project
node app.js
로 애플리케이션을 시작합니다.
- node app.js
브라우저에서 http://your_server_ip:8080
으로 이동합니다. 다음은 방문 페이지입니다.
Get Shark Info 버튼을 클릭하면 다음 정보 페이지로 이동합니다.
이제 애플리케이션이 실행되고 있습니다. 준비가 되면 CTRL + C
를 입력하여 서버를 종료합니다. 이제 원하는 대로 이 애플리케이션을 재생성하고 확장할 수 있는 Dockerfile 생성으로 이동할 수 있습니다.
3단계 - Dockerfile 작성
Dockerfile은 애플리케이션이 실행될 때 애플리케이션 컨테이너에 포함될 항목을 지정합니다. Dockerfile을 사용하면 컨테이너 환경을 정의하고 종속성 또는 런타임 버전과의 불일치를 방지할 수 있습니다.
최적화된 컨테이너 구축에 대한 이러한 지침을 따르면 이미지 레이어 수를 최소화하고 이미지의 기능을 애플리케이션 파일 및 정적 콘텐츠 재생성이라는 단일 목적으로 제한하여 이미지를 최대한 효율적으로 만들 수 있습니다.
프로젝트의 루트 디렉터리에서 Dockerfile을 만듭니다.
- nano Dockerfile
Docker 이미지는 서로 위에 빌드되는 일련의 계층화된 이미지를 사용하여 생성됩니다. 첫 번째 단계는 애플리케이션 빌드의 시작점을 형성할 애플리케이션의 기본 이미지를 추가하는 것입니다.
Docker 허브 노드 이미지 페이지를 사용할 수 있습니다.
다음 FROM
명령어를 추가하여 애플리케이션의 기본 이미지를 설정합니다.
FROM node:10-alpine
이 이미지에는 Node.js 및 npm이 포함되어 있습니다. 각 Dockerfile은 FROM
명령어로 시작해야 합니다.
기본적으로 Docker 노드 이미지에는 애플리케이션 컨테이너를 루트로 실행하지 않도록 하는 데 사용할 수 있는 루트가 아닌 노드 사용자가 포함됩니다. 컨테이너를 루트로 실행하지 않고 모범 사례 가이드로 권장되는 보안 사례입니다.
컨테이너에서 애플리케이션 코드에 대한 권한을 미세 조정하려면 app
디렉터리와 함께 /home/node
에 node_modules
하위 디렉터리를 만듭니다. 이러한 디렉터리를 만들면 올바른 권한을 갖게 됩니다. 이는 npm install
을 사용하여 컨테이너에 로컬 노드 모듈을 만들 때 중요합니다. 이러한 디렉토리를 생성하는 것 외에도 소유권을 노드 사용자로 설정하십시오.
...
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
통합 RUN
명령의 유틸리티에 대한 자세한 내용은 컨테이너 계층 관리 방법에 대한 이 토론을 참조하십시오.
다음으로 애플리케이션의 작업 디렉터리를 /home/node/app
로 설정합니다.
...
WORKDIR /home/node/app
WORKDIR
이 설정되지 않은 경우 Docker는 기본적으로 하나를 생성하므로 명시적으로 설정하는 것이 좋습니다.
다음으로 package.json
및 package-lock.json
(npm 5+용) 파일을 복사합니다.
...
COPY package*.json ./
npm install
을 실행하거나 애플리케이션 코드를 복사하기 전에 이 COPY
명령을 추가하면 Docker의 캐싱 메커니즘을 활용할 수 있습니다. 빌드의 각 단계에서 Docker는 특정 명령에 대해 캐시된 계층이 있는지 확인합니다. package.json
을 변경하면 이 레이어가 다시 빌드되지만 그렇지 않으면 이 지침을 통해 Docker가 기존 이미지 레이어를 사용하고 노드 모듈 재설치를 건너뛸 수 있습니다.
node_modules
디렉터리의 콘텐츠를 포함하여 루트가 아닌 노드 사용자가 모든 애플리케이션 파일을 소유하도록 하려면 npm install
을 실행하기 전에 사용자를 노드로 전환합니다.
...
USER node
프로젝트 종속성을 복사하고 사용자를 전환한 후 npm install
을 실행합니다.
...
RUN npm install
다음으로 컨테이너의 애플리케이션 디렉터리에 대한 적절한 권한이 있는 애플리케이션 코드를 복사합니다.
...
COPY --chown=node:node . .
이렇게 하면 루트가 아닌 노드 사용자가 애플리케이션 파일을 소유하게 됩니다.
마지막으로 컨테이너에서 포트 8080
을 노출하고 애플리케이션을 시작합니다.
...
EXPOSE 8080
CMD [ "node", "app.js" ]
EXPOSE
는 포트를 게시하지 않지만 대신 런타임에 게시될 컨테이너의 포트를 문서화하는 방법으로 작동합니다. CMD
는 응용 프로그램을 시작하는 명령을 실행합니다. 이 경우에는 node app.js
입니다.
참고: 각 Dockerfile에는 하나의 CMD
명령어만 있어야 합니다. 둘 이상 포함하면 마지막 항목만 적용됩니다.
Dockerfile로 할 수 있는 일이 많습니다. 전체 지침 목록은 Docker의 Dockerfile 참조 문서를 참조하세요.
다음은 완전한 Dockerfile입니다.
FROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "app.js" ]
편집을 마치면 파일을 저장하고 닫습니다.
애플리케이션 이미지를 빌드하기 전에 .gitignore
파일을 추가하세요. .dockerignore
는 프로젝트 디렉터리의 어떤 파일과 디렉터리를 컨테이너로 복사하면 안 되는지 지정합니다.
.dockerignore
파일을 엽니다.
- nano .dockerignore
파일 내에서 로컬 노드 모듈, npm 로그, Dockerfile 및 .dockerignore
파일을 추가합니다.
node_modules
npm-debug.log
Dockerfile
.dockerignore
Git으로 작업하는 경우 .git
디렉토리와 .gitignore
파일도 추가해야 합니다.
완료되면 파일을 저장하고 닫습니다.
이제 docker build
명령을 사용하여 애플리케이션 이미지를 빌드할 준비가 되었습니다. docker build
와 함께 -t
플래그를 사용하면 기억하기 쉬운 이름으로 이미지에 태그를 지정할 수 있습니다. 이미지를 Docker Hub로 푸시할 것이므로 태그에 Docker Hub 사용자 이름을 포함합니다. 이미지에 nodejs-image-demo
태그를 지정할 수 있지만 원하는 이름으로 교체해도 됩니다. your_dockerhub_username
도 자신의 Docker Hub 사용자 이름으로 바꿔야 합니다.
- docker build -t your_dockerhub_username/nodejs-image-demo .
.
는 빌드 컨텍스트가 현재 디렉토리임을 지정합니다.
이미지를 구축하는 데 약간의 시간이 걸립니다. 완료되면 이미지를 확인합니다.
- docker images
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 73MB
node 10-alpine f09e7c96b6de 13 monthss ago 82.7MB
이제 docker run
을 사용하여 이 이미지로 컨테이너를 생성할 수 있습니다. 이 명령에는 세 가지 플래그가 포함됩니다.
-p
: 컨테이너의 포트를 게시하고 호스트의 포트에 매핑합니다. 호스트에서 포트80
을 사용할 수 있지만 해당 포트에서 실행 중인 다른 프로세스가 있는 경우 필요에 따라 자유롭게 수정할 수 있습니다. 작동 방식에 대한 자세한 내용은 포트 바인딩에 대한 Docker 문서에서 이 토론을 참조하세요.-d
: 백그라운드에서 컨테이너를 실행합니다.--name
: 이를 통해 컨테이너에 기억하기 쉬운 이름을 지정할 수 있습니다.
다음 명령어를 실행하여 컨테이너를 빌드합니다.
- docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
컨테이너가 실행되면 docker ps
를 사용하여 실행 중인 컨테이너 목록을 검사할 수 있습니다.
- docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e50ad27074a7 your_dockerhub_username/nodejs-image-demo "docker-entrypoint.s…" 13 seconds ago Up 12 seconds 0.0.0.0:80->8080/tcp, :::80->8080/tcp nodejs-image-demo
컨테이너가 실행 중이면 이제 브라우저에서 http://your_server_ip
로 이동하여 애플리케이션을 방문할 수 있습니다.
이제 애플리케이션용 이미지를 만들었으므로 나중에 사용할 수 있도록 Docker Hub에 푸시할 수 있습니다.
4단계 - 리포지토리를 사용하여 이미지 작업
Docker Hub와 같은 레지스트리에 애플리케이션 이미지를 푸시하면 나중에 컨테이너를 빌드하고 확장할 때 사용할 수 있습니다. 이것이 어떻게 작동하는지 보여주기 위해 애플리케이션 이미지를 리포지토리에 푸시한 다음 이미지를 사용하여 컨테이너를 다시 만듭니다.
이미지를 푸시하는 첫 번째 단계는 전제 조건에서 만든 Docker Hub 계정에 로그인하는 것입니다.
- docker login -u your_dockerhub_username
메시지가 표시되면 Docker Hub 계정 암호를 입력합니다. 이 방법으로 로그인하면 Docker Hub 자격 증명을 사용하여 사용자의 홈 디렉터리에 ~/.docker/config.json
파일이 생성됩니다.
이제 이전에 만든 your_dockerhub_username/nodejs-image-demo
태그를 사용하여 애플리케이션 이미지를 Docker Hub에 푸시할 수 있습니다.
- docker push your_dockerhub_username/nodejs-image-demo
현재 애플리케이션 컨테이너와 이미지를 삭제하고 리포지토리의 이미지로 다시 빌드하여 이미지 레지스트리의 유틸리티를 테스트해 보겠습니다.
먼저 실행 중인 컨테이너를 나열합니다.
- docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e50ad27074a7 your_dockerhub_username/nodejs-image-demo "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:80->8080/tcp, :::80->8080/tcp nodejs-image-demo
출력에 나열된 CONTAINER ID
를 사용하여 실행 중인 애플리케이션 컨테이너를 중지합니다. 아래 강조표시된 ID를 자신의 컨테이너 ID
로 바꾸십시오.
- docker stop e50ad27074a7
-a
플래그를 사용하여 모든 이미지를 나열하십시오.
- docker images -a
다음은 node
your_dockerhub_username/nodejs-image-demo와 함께 출력됩니다. > 빌드의 이미지 및 기타 이미지:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 7 minutes ago 73MB
<none> <none> 2e3267d9ac02 4 minutes ago 72.9MB
<none> <none> 8352b41730b9 4 minutes ago 73MB
<none> <none> 5d58b92823cb 4 minutes ago 73MB
<none> <none> 3f1e35d7062a 4 minutes ago 73MB
<none> <none> 02176311e4d0 4 minutes ago 73MB
<none> <none> 8e84b33edcda 4 minutes ago 70.7MB
<none> <none> 6a5ed70f86f2 4 minutes ago 70.7MB
<none> <none> 776b2637d3c1 4 minutes ago 70.7MB
node 10-alpine f09e7c96b6de 13 months ago 82.7MB
다음 명령을 사용하여 중지된 컨테이너와 사용되지 않거나 매달린 이미지를 포함한 모든 이미지를 제거합니다.
docker system prune -a
중지된 컨테이너와 이미지를 제거할 것인지 확인하는 메시지가 출력에 표시되면 y
를 입력합니다. 이렇게 하면 빌드 캐시도 제거됩니다.
이제 애플리케이션 이미지를 실행하는 컨테이너와 이미지 자체를 모두 제거했습니다. Docker 컨테이너, 이미지 및 볼륨 제거에 대한 자세한 내용은 Docker 이미지, 컨테이너 및 볼륨 제거 방법을 참조하십시오.
모든 이미지와 컨테이너가 삭제되었으므로 이제 Docker Hub에서 애플리케이션 이미지를 가져올 수 있습니다.
- docker pull your_dockerhub_username/nodejs-image-demo
이미지를 다시 한 번 나열합니다.
- docker images
애플리케이션 이미지가 표시됩니다.
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 11 minutes ago 73MB
이제 3단계의 명령을 사용하여 컨테이너를 다시 빌드할 수 있습니다.
- docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
실행 중인 컨테이너를 나열합니다.
- docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6bc2f50dff6 your_dockerhub_username/nodejs-image-demo "docker-entrypoint.s…" 6 seconds ago Up 5 seconds 0.0.0.0:80->8080/tcp, :::80->8080/tcp nodejs-image-demo
실행 중인 애플리케이션을 보려면 http://your_server_ip
를 다시 한 번 방문하십시오.
결론
이 자습서에서는 Express 및 Bootstrap을 사용하여 정적 웹 애플리케이션과 이 애플리케이션에 대한 Docker 이미지를 만들었습니다. 이 이미지를 사용하여 컨테이너를 만들고 이미지를 Docker Hub에 푸시했습니다. 거기에서 이미지와 컨테이너를 제거하고 Docker Hub 리포지토리를 사용하여 다시 만들 수 있습니다.
Docker Compose 및 Docker Machine과 같은 도구를 사용하여 다중 컨테이너 설정을 만드는 방법에 대해 자세히 알아보려면 다음 가이드를 참조하세요.
- Ubuntu 18.04에 Docker Compose를 설치하는 방법
- Ubuntu 18.04에서 Docker 머신으로 원격 Docker 호스트를 프로비저닝하고 관리하는 방법
컨테이너 데이터 작업에 대한 일반적인 팁은 다음을 참조하세요.
- Docker 컨테이너 간에 데이터를 공유하는 방법.
- Docker 컨테이너와 호스트 간에 데이터를 공유하는 방법.
다른 Docker 관련 항목에 관심이 있는 경우 전체 Docker 자습서 라이브러리를 참조하십시오.