---
title: "Hướng Dẫn Tạo Ứng Dụng NodeJS với Docker"
description: "Nền tảng Docker cho phép các nhà phát triển đóng gói và chạy ứng dụng dưới dạng các container. Một container là một tiến trình được cô lập, chạy trên cùng hệ điều hành chia sẻ, cung cấp một lựa chọn nhẹ hơn so với máy ảo. Dù container không phải là mới, chúng mang lại nhiều lợi ích — bao gồm cô lập tiến trình và chuẩn hóa môi trường — ngày càng trở nên quan trọng khi nhiều nhà phát triển sử dụng kiến trúc ứng dụng phân tán."
url: https://cloudfly.vn/huong-dan-tao-ung-dung-nodejs-voi-docker
image: https://media.cloudfly.vn/posts/huong-dan-tao-ung-dung-node-js-voi-docker.png
---

# Hướng Dẫn Tạo Ứng Dụng NodeJS với Docker

![description image](https://media.cloudfly.vn/posts/huong-dan-tao-ung-dung-node-js-voi-docker.png)

Nền tảng Docker cho phép các nhà phát triển đóng gói và chạy ứng dụng dưới dạng **container**. Một container là một tiến trình được cô lập chạy trên cùng một hệ điều hành chia sẻ, cung cấp một lựa chọn nhẹ hơn so với máy ảo. Dù container không phải là mới, chúng mang lại lợi ích — bao gồm cô lập tiến trình và chuẩn hóa môi trường — ngày càng quan trọng khi nhiều nhà phát triển sử dụng kiến trúc ứng dụng phân tán.

Khi xây dựng và mở rộng ứng dụng với Docker, điểm bắt đầu thường là tạo một image cho ứng dụng của bạn, bạn có thể chạy trong container. Image bao gồm mã ứng dụng, thư viện, file cấu hình, biến môi trường và runtime. Sử dụng image giúp chuẩn hóa môi trường trong container và chỉ chứa những gì cần thiết để xây dựng và chạy ứng dụng.

Trong bài hướng dẫn này, bạn sẽ tạo image ứng dụng cho một website tĩnh sử dụng framework Express và Bootstrap. Sau đó, bạn sẽ xây dựng container từ image đó và đẩy lên Docker Hub để sử dụng về sau. Cuối cùng, bạn sẽ kéo lại image từ kho Docker Hub và tạo container khác, thể hiện cách tái tạo và mở rộng ứng dụng.

## Hướng dẫn tạo ứng dụng NodeJS với Docker

### Bước 1 — Cài Đặt Các Phụ Thuộc Của Ứng Dụng

Để tạo image, trước hết bạn cần tạo các file ứng dụng, bao gồm nội dung tĩnh, mã nguồn và phụ thuộc.

Tạo thư mục dự án trong thư mục home của người dùng không phải root. Ví dụ đặt tên `node_project`:

```bash
mkdir node_project
cd node_project
```

Tạo file `package.json` chứa thông tin phụ thuộc và các thông tin định danh khác:

```bash
nano package.json
```

Chèn nội dung sau, thay đổi tên tác giả và thông tin liên hệ:

```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"
  }
}
```

File này bao gồm tên dự án, tác giả và giấy phép phân phối (MIT). Thuộc tính `main` chỉ ra điểm vào ứng dụng là `app.js`. Phần `dependencies` liệt kê các thư viện cần thiết, ở đây là Express 4.16.4 trở lên.

Lưu và đóng file. Cài đặt các phụ thuộc trong dự án:

```bash
npm install
```

---

### Bước 2 — Tạo Các File Ứng Dụng

Chúng ta sẽ tạo một website cung cấp thông tin về cá mập. Ứng dụng có điểm vào chính là `app.js` và thư mục `views` chứa tài nguyên tĩnh. Trang chính `index.html` cung cấp thông tin sơ bộ và liên kết đến trang chi tiết `sharks.html`. Cả hai trang này sẽ nằm trong `views`.

Mở `app.js` để định nghĩa các route:

```bash
nano app.js
```

Thêm mã sau để tạo ứng dụng Express, đối tượng router, và định nghĩa thư mục cơ sở cùng cổng lắng nghe 8080:

```javascript
const express = require('express');
const app = express();
const router = express.Router();

const path = __dirname + '/views/';
const port = 8080;
```

`require` tải module express, tạo đối tượng `app` và `router`. `router` chịu trách nhiệm điều hướng các yêu cầu HTTP.

Định nghĩa các tuyến bằng `router`:

```javascript
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` đăng ký middleware để ghi log các yêu cầu; `router.get` định nghĩa phản hồi cho các đường dẫn `/` và `/sharks`.

Cuối cùng, kết nối middleware và tài nguyên tĩnh, lắng nghe trên cổng 8080:

```javascript
app.use(express.static(path));
app.use('/', router);

app.listen(port, function () {
  console.log('Example app listening on port 8080!');
});
```

Lưu và đóng file.

Tạo thư mục `views` và file `index.html`:

```bash
mkdir views
nano views/index.html
```

Thêm mã HTML sau để tạo trang chính:

```html
<!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>
```

Lưu và đóng file.

Tạo file `sharks.html` trong `views` có nội dung chi tiết về cá mập:

```bash
nano views/sharks.html
```

Thêm mã HTML sau:

```html
<!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="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.digitalocean.com/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.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
            </p>
        </div>
    </div>
</div>
</body>
</html>
```

Lưu và đóng file.

Tạo thư mục `css` trong `views` và tạo file `styles.css` để tạo style tùy chỉnh:

```bash
mkdir views/css
nano views/css/styles.css
```

Thêm CSS:

```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;
}
```

Lưu file.

Để bắt đầu ứng dụng, nếu bạn có tường lửa chỉ cho phép SSH, hãy mở cổng 8080:

```bash
sudo ufw allow 8080
```

Vào thư mục dự án và chạy:

```bash
cd ~/node_project
node app.js
```

Truy cập `http://your_server_ip:8080` trên trình duyệt để xem trang chủ. Nhấn nút **Get Shark Info** để xem trang chi tiết về cá mập.

Nhấn `CTRL+C` để tắt server.

---

### Bước 3 — Viết Dockerfile

Dockerfile định nghĩa môi trường container khi chạy ứng dụng. Tuân theo các hướng dẫn tối ưu, ta giảm số lớp ảnh và giới hạn chức năng image cho việc tái tạo ứng dụng tĩnh.

Tạo Dockerfile trong thư mục dự án:

```bash
nano Dockerfile
```

Chọn ảnh base là `node:10-alpine` (phiên bản LTS Node.js đề xuất):

```dockerfile
FROM node:10-alpine
```

Tạo thư mục `node_modules` trong `/home/node/app` và đặt quyền sở hữu cho user `node`:

```dockerfile
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
```

Đặt thư mục làm việc:

```dockerfile
WORKDIR /home/node/app
```

Sao chép file `package.json` và `package-lock.json`:

```dockerfile
COPY package*.json ./
```

Chuyển sang user `node`:

```dockerfile
USER node
```

Cài đặt các phụ thuộc:

```dockerfile
RUN npm install
```

Sao chép toàn bộ mã ứng dụng, đổi quyền sở hữu cho user `node`:

```dockerfile
COPY --chown=node:node . .
```

Mở cổng 8080:

```dockerfile
EXPOSE 8080
```

Chạy ứng dụng:

```dockerfile
CMD [ "node", "app.js" ]
```

Lưu và đóng Dockerfile.

Tạo file `.dockerignore` để ngăn chặn sao chép các file/directory không cần thiết:

```bash
nano .dockerignore
```

Thêm nội dung:

```
node_modules
npm-debug.log
Dockerfile
.dockerignore
```

Lưu và đóng file.

Xây dựng image với tag bao gồm tên user Docker Hub:

```bash
sudo docker build -t your_dockerhub_username/nodejs-image-demo .
```

Kiểm tra các image:

```bash
sudo docker images
```

Chạy container:

```bash
sudo docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
```

Kiểm tra container chạy:

```bash
sudo docker ps
```

Mở trình duyệt đến `http://your_server_ip` để xem trang chủ.

---

### Bước 4 — Sử Dụng Kho Lưu Trữ Để Quản Lý Image

Đăng nhập Docker Hub:

```bash
sudo docker login -u your_dockerhub_username
```

Nhập mật khẩu khi được yêu cầu.

Đẩy image lên Docker Hub:

```bash
sudo docker push your_dockerhub_username/nodejs-image-demo
```

Kiểm tra container đang chạy:

```bash
sudo docker ps
```

Dùng container ID dừng container:

```bash
sudo docker stop container_id
```

Xem toàn bộ image:

```bash
docker images -a
```

Dọn dẹp container và image không dùng với:

```bash
docker system prune -a
```

Gõ `y` để xác nhận.

Kéo lại image từ Docker Hub:

```bash
docker pull your_dockerhub_username/nodejs-image-demo
```

Kiểm tra image:

```bash
docker images
```

Tạo lại container như bước 3:

```bash
docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo
```

Kiểm tra container:

```bash
docker ps
```

Truy cập `http://your_server_ip` để xem ứng dụng đang chạy.

---

## Kết Luận

Trong bài hướng dẫn này, bạn đã tạo ứng dụng web tĩnh với Express và Bootstrap, xây dựng image Docker cho ứng dụng, tạo container từ image và đẩy lên Docker Hub. Bạn cũng đã học cách xóa và tái tạo container cũng như image từ repository Docker Hub.

Nếu bạn quan tâm học cách làm việc với Docker Compose hoặc Docker Machine để tạo setup đa container, hãy tham khảo các hướng dẫn liên quan. Ngoài ra, cũng có các hướng dẫn chia sẻ dữ liệu giữa các container và giữa container với host, rất hữu ích khi làm việc với Docker.

Bạn có thể duyệt thư viện hướng dẫn Docker đầy đủ trên trang của chúng tôi để tìm hiểu thêm về các chủ đề liên quan.
