# Vue.js
# Nginx + Vue.js 배포를 위한 설정
# Step 1. 기본 위치 설정
- target server: linux (centos 8)
- 배포 방식: docker-compose 를 이용한 nginx container
# 배포 디렉토리
$ mkdir dist
# certbot 인증서 저장경로
$ mkdir certbot-etc
# nginx config
$ mkdir nginx-conf
1
2
3
4
5
6
2
3
4
5
6
dist
: vue app 빌드한 결과를 여기에 넣고 호스팅하기 위한 디렉토리certbot-etc
: letsencrypt 인증서 저장 디렉토리nginx-conf
: nginx config 디렉토리
# Step 2. certbot 을 통한 인증서 생성
- 인증서 생성만을 위한
nginx.conf
작성
server {
listen 80;
listen [::]:80;
server_name temp.temp.io;
index index.html index.htm;
root /var/www/html;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
try_files $uri $uri/ /index.html;
}
location ~ /\.ht {
deny all;
}
location = /favicon.ico {
log_not_found off; access_log off;
}
location = /robots.txt {
log_not_found off; access_log off; allow all;
}
location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
}
}
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
33
34
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
33
34
docker-compose.yml
를 통해 인증서 생성 시작
version: '3'
services:
certbot:
depends_on:
- webserver
image: certbot/certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
- ./dist:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email temp@gmail.com --agree-tos --no-eff-email --staging -d temp.temp.io
webserver:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./dist:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- ./certbot-etc:/etc/letsencrypt
networks:
- app-network
volumes:
certbot-etc:
dist:
nginx-conf:
networks:
app-network:
driver: bridge
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
33
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
33
TIP
certbot 의 --staging 은 테스트 한다는 의미
email, domain 은 적절하게 수정
$ docker-compose up -d
Name Command State Ports
-----------------------------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
webserver /docker-entrypoint.sh ngin ... Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
1
2
3
4
5
2
3
4
5
TIP
certbot 은 Exit 0 가 되는 것이 맞음. 인증서 생성이 되면 ./certbot-etc 에 가면 확인할 수 있음
docker-compose.yml
의 certbot command 수정
...
certbot:
depends_on:
- webserver
image: certbot/certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
- ./dist:/var/www/html
command: certonly --webroot --webroot-path=/var/www/html --email temp@gmail.com --agree-tos --no-eff-email --force-renewal -d temp.temp.io
...
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
$ docker-compose up --force-recreate --no-deps certbot
1
# Step 3. ssl 적용
- ssl 관련 설정 다운로드
$ curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf
1
- nginx 설정 수정
server {
listen 80;
listen [::]:80;
server_name temp.temp.io;
index index.html index.htm;
root /var/www/html;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
try_files $uri $uri/ /index.html;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name temp.temp.io;
index index.html index.htm;
root /var/www/html;
server_tokens off;
client_max_body_size 100M;
ssl_certificate /etc/letsencrypt/live/temp.temp.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/temp.temp.io/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/temp.temp.io/chain.pem;
include /etc/nginx/conf.d/options-ssl-nginx.conf;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
location / {
try_files $uri $uri/ /index.html;
}
}
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ docker-compose up -d --force-recreate --no-deps webserver
1
- 인증서 자동 갱신을 위한 스크립트 작성 후 crontab 에 등록
ssl_renew.sh
#!/bin/bash
COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"
cd /home/temp/vuejsapp/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af
1
2
3
4
5
6
7
2
3
4
5
6
7
$ chmod +x ssl_renew.sh
$ sudo crontab -e
0 12 * * * /home/temp/vuejsapp/ssl_renew.sh >> /var/log/cron.log 2>&1
1
2
3
4
2
3
4
docker-compose.yml
의 certbot command 수정
...
certbot:
depends_on:
- webserver
image: certbot/certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
- ./dist:/var/www/html
command: renew
...
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
$ docker-compose up --force-recreate --no-deps certbot
1
# Step 4. /dist vue.js 앱 배포
yarn build
등을 통해 빌드된 결과를/dist
에 복사
# nginx + vue.js 를 docker 를 통해 배포
- 호스트에 이미 docker 를 통한 reverse proxy 가 설정되어 있다는 가정하에 시작합니다.
- docker 를 통한 reverse proxy 설정은 다음 (opens new window)을 참고합니다.
- 참조: Dockrize Vue.js App (opens new window)
- 해당 앱 디렉토리에
nginx.conf
를 추가합니다. (vue router history mode 관련 설정을 추가합니다.)
server {
listen 8080;
client_max_body_size 5M;
location / {
alias /usr/share/nginx/html/;
try_files $uri $uri/ /index.html;
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Dockerfile
# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN yarn
COPY . .
RUN yarn build
# production stage
FROM nginx:stable-alpine as production-stage
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY /app/dist /usr/share/nginx/html
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
TIP
- docker build 를 통해 이미지 생성 후 ghcr.io 에 배포는 다음과 같이 진행했습니다.
- ghcr.io 로그인은 다음 (opens new window)을 참고합니다.
$ docker build -t ghcr.io/shockzinfinity/vuejs-app:latest .
# ghcr.io 에 로그인 되어있다고 가정
$ docker push ghcr.io/shockzinfinity/vuejs-app:latest
1
2
3
2
3
docker-compose.yml
version: '3'
services:
vuejs-app:
container_name: vuejs-app
image: ghcr.io/shockzinfinity/vuejs-app:latest
environment:
- VIRTUAL_HOST=vuejs.your.domain
- VIRTUAL_PORT=8080
- LETSENCRYPT_HOST=vuejs.your.domain
- LETSCRYPT_EMAIL=email@your.domain
networks:
default:
external:
name: nginx-proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 결과 확인
$ docker-compose up -d
$ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------
vuejs-app /docker-entrypoint.sh ngin ... Up 80/tcp, 8080/tcp
1
2
3
4
5
2
3
4
5