Nginx Learning Journey


Cấu hình

Yêu cầu:

  • Sử dụng HDH linux, ở đây mình dùng Ubuntu.
  • Cài đặt docker
  • Cài đặt node.js và npm

Docker & nginx cơ bản

Để thuận tiện, ở đây mình xây dựng nginx trên docker. Bạn nào chưa biết dùng docker thì có thể xem bài viết cũ của mình ở đây.

Cấu trúc file:

1
2
3
├── docker-compose.yml
└── reverse_proxy
└── nginx.conf

Nội dung file docker-compose.yml:

  • Nginx là một máy chủ web được cấu hình bằng tập tin nginx.conf, file cấu hình nginx thường được đặt trong /etc/nginx/nginx.conf. Cho nên chúng ta cần copy file nginx.conf vào /etc/nginx/nginx.conf ở volumes trong docker-compose.yml file.
1
2
3
4
5
6
7
8
9
10
version: '3'

services:
reverse-proxy:
image: nginx:1.23.4
container_name: reverse_proxy_demo
volumes:
- ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80

Nội dung file nginx.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
keepalive_timeout 65;
# Ta chỉ cần tập trung vào cấu hình server này.
server {
listen 80;
server_name localhost;

location / {
return 200 "Hello World";
}
}
}

Khởi chạy: docker compose up -d hoặc nếu bạn đã cài gói docker-compose thì dùng docker-compose up -d.

Dùng docker ps để xem container đang chạy. Nó đã chạy trên port 80, bây giờ truy cập localhost:80 để xem kết quả.

Uke, server đã chạy nhưng chỉ đơn giản là trả về file có nội dung Hello World. Ta cùng học tiếp nhé~

Chạy docker compose down để gỡ container đi, nếu bạn có cài những container khác mà không muốn mất thì nhớ chỉ định đúng container để gỡ, ở đây là docker compose down reverse_proxy_demo

Render html file

Tạo thêm file html/index.html:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html lang="en">

<body>
<h1>Hello world!</h1>
</body>

</html>

Cây thư mục:

1
2
3
4
5
├── docker-compose.yml
├── html
│   └── index.html
└── reverse_proxy
└── nginx.conf

Đưa thư mục html vào container:

1
2
3
4
5
6
7
8
9
10
11
version: '3'

services:
reverse-proxy:
image: nginx:1.23.4
container_name: reverse_proxy_demo
volumes:
- ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
- ./html:/html
ports:
- 80:80

Nắm một xíu về chỉ thị root trong nginx:

  • Chỉ thị root được sử dụng để chỉ định đường dẫn tới thư mục gốc (root directory) chứa các tập tin tĩnh (ví dụ: các tập tin HTML, CSS, JavaScript, hình ảnh, v.v.) được phục vụ bởi Nginx.
  • Nếu bạn đặt root /html; trong cấu hình Nginx, thì khi có yêu cầu truy cập đến server, Nginx sẽ tìm kiếm các tập tin tĩnh trong thư mục /html để phục vụ cho yêu cầu đó.

Chỉnh sửa file nginx.conf:

1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name localhost;

location / {
root /html;
index index.html;
}
}

Hoặc chúng ta có thể đặt đường dẫn root cho toàn bộ server:

1
2
3
4
5
6
7
8
9
server {
listen 80;
root /html;
server_name localhost;

location / {
index index.html;
}
}

Khởi chạy docker compose up -d. Truy cập localhost, file index.html đã được khởi chạy trên browser.

Đặt chỉ thị error_page để xử lý 404 not Found

Thường thì này cũng không cần thiết lắm, nhưng mình có thể tự xử lý status 404 riêng.

Thêm file 404.html vào thư mục html.

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<title>404 - Not Found</title>
</head>
<body>
<h1>404 - Not Found</h1>
<p>Oh no bro, you're going down a path that even a saint like me can't handle.</p>
</body>
</html>

Thêm chỉ thị error_page:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
root /html;
server_name localhost;

location / {
index index.html;
}

error_page 404 /404.html;
}

Khởi chạy: docker compose up -d (nhớ docker compose down trước nhé).

Truy cập localhost/abjdkje, trang lỗi đã được đổi thành trang 404.html của mình.

Chỉ thị proxy_pass

Công dụng của nginx là điều hướng người dùng,… nên proxy_pass là một điều mà không thể không nhắc đến.

Mình sẽ tạo một node.js web app cơ bản để demo cho rõ nhé.

Thêm thư mục app:

  • Đi đến thư mục appnpm init -y
  • Tiếp theo chạy lệnh npm install express
  • Tạo file app.js:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const express = require('express');

    const app = express();
    const PORT = 8080;

    app.get('/', (req, res) => {
    res.send('Hello world!');

    });

    app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
    });
  • Tạo file Dockerfile:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    FROM node:14

    WORKDIR /app

    COPY package*.json /app

    RUN npm install

    COPY . /app

    EXPOSE 8080

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

Sau khi chạy xong ta sẽ có cây thư mục như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
.
├── app
│   ├── node_modules
│   ├── app.js
│   ├── Dockerfile
│   ├── package.json
│   └── package-lock.json
├── docker-compose.yml
├── html
│   ├── 404.html
│   └── index.html
└── reverse_proxy
└── nginx.conf

Chỉnh sửa docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: '3'

services:
node-app:
build: ./app
container_name: node_app_demo
ports:
- 8080:8080
reverse-proxy:
image: nginx:1.23.4
container_name: reverse_proxy_demo
volumes:
- ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
- ./html:/html
ports:
- 80:80
depends_on:
- node-app

Notes:

  • Trong một môi trường Docker Compose, các dịch vụ (services) được định nghĩa trong docker-compose.yml được xem như các tên miền. Khi bạn đặt tên cho dịch vụ trong docker-compose.yml (ví dụ: node-app), Docker Compose sẽ tạo một mạng mặc định giữa các dịch vụ và sử dụng tên của dịch vụ đó làm tên miền để chúng có thể giao tiếp với nhau.
  • Để nginx chuyển hướng đến node-app thì chúng ta phải set tên miền là http://node-app:8080 tuy nhiên do ở đây mình đặt tên lại cho container là node_app_demo nên chúng ta sẽ set là http://node_app_demo:8080.
  • Nếu chúng ta đặt là http://localhost:8080 thì nginx sẽ chuyển hướng đến localhost của container nginx chứ không phải là node_app_demo.

Cấu hình lại nginx.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://node_app_demo:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

error_page 404 /404.html;

location /404.html {
root /html;
}
}

Với cấu hình trên, khi người dùng truy cập đến http://localhost/ thì nginx sẽ điều hướng đến container node_app_demo.

Khởi chạy: docker compose up -d

Thư mục của mình để ở đây