很久没写前端相关的文章,因为主要精力都花在其他技术上去了......
这次是因为有小伙伴问到了怎么方便的把前端的项目加入到整个项目的工作流程中。 她参与的是一个大型数据项目,项目采用了 k8s 部署。
但给前端的资源就只有 nginx 和 node 服务。 以她参与的前端的实际情况,拆分掉很多的复杂度,简化出自定义 nginx 和多阶段构建两个部分,匆忙写出此篇方便小伙伴快速上手项目部署。
前端自定义 nginx 和多阶段构建
容器中怎么自定义 nginx
你已经知道了 nginx 配置文件怎么写了,在 docker 中怎么写改配置文件? 难道每次都进入 nginx container 手动改么?
基础
- nginx: www.nginx.com/ 熟练掌握 nginx 的配置文件的写法
- nginx docker image: hub.docker.com/_/nginx?tab…
下面的内容假设你已经充分了解了 nginx 的配置文件的意思和写法;假设你已经充分了解过 docker 的常见操作。
下面逐步介绍解决方案。
启动默认的 nginx
docker run --name mynginx -d -p 80:80 nginx
复制代码
浏览器访问 http://localhost/
出现 nginx 的欢迎界面。
查看 nginx 配置文件
# 进入容器
docker exec -it mynginx /bin/bash
# 查看默认的配置文件
cat /etc/nginx/nginx.conf
#上面的命令在控制的输出的文件的内容,看到最下面一行的内容是
include /etc/nginx/conf.d/*.conf;
# 进入相应目录查看内容
cd /etc/nginx/conf.d
ls -al # 发现只有一个 default.conf
cat default.conf # 输出默认 server 的配置输出内容如下
复制代码
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
复制代码
我们可以看到这个服务的的根目录是: /usr/share/nginx/html
;默认的端口是 80。
# 进入 nginx 的默认根目录,查看里面的内容
# 默认里面只有 50x.html 和 index.html
cd /usr/share/nginx/html
复制代码
我们修改 /usr/share/nginx/html
里面的内容为自己的前端需要部署的静态文件,那前端跑在 nginx 上不就可以了么?
定制方案一:docker cp
我们定制修改 /usr/share/nginx/html
里面的内容。
我自己的前端文件在: /Users/xiezhongfu/Workspace/m-company/packages/front/dist
,现在把个文件的里面的内容全部复制到 mynginx
容器的 /usr/share/nginx/html
路径下。
docker cp 源文件路径 容器id:/usr/share/nginx/html
# 进入容器,容器 id 为 6262cc2b1a2e
docker exec -it 6262cc2b1a2e /bin/bash
# 进入 html 文件夹,备份原来的 index.html
cd /usr/share/nginx/html
cp index.html index_backup.html
# 把 html下的 dist 文件夹下的内容复制到 html 本层文件夹
mv ./dist/* *
复制代码
刷新网页查看,正常显示前端的内容。
定制方案一升级版 A
- 如果不想修改默认的 nginx 配置根路径下的内容,想定制一个根路径
- 如果还需要配置接口转发
因为 nginx 的配置文件了加载了 /etc/nginx/conf.d 文件下的所有文件, 我们可以把需要的 server 配置文件通过 docker cp 的方式传到 /etc/nginx/conf.d 。
升级版的核心点是
- 启动 nginx 服务
- 通过 docker cp 的方式把把一个自定义的 server 配置文件传到容器的 /etc/nginx/conf.d 下
- 并重启 nginx 服务
定制方案一升级版 B
在升级版 A 中只是实现了 nginx 的 server 自定一,如果你想完全替换默认的 nginx 呢?
那就把 /etc/nginx/nginx.conf 替换即可。
定制方案二:volume 同步文件
使用 volume 的,docker 自动同步宿主机和容器的文件,达到和 docker cp 同样的道理。
同步静态文件
docker run --name mynginx -v /some/content1:/usr/share/nginx/html -d nginx
复制代码
同步配置文件
docker run --name mynginx -v /some/content2:/etc/nginx/conf.d -d nginx
复制代码
定制方案三:基于 nginx 自定义镜像
Dockerfile
- 基于 nginx 基础镜像
- 把前端构建好的内容复制到镜像某个路径中
- 替换原镜像中的 nginx 配置文件
- 依然使用了 nginx 基础镜像的 CMD 命令,不覆写。如果想要覆写启动命令怎么办呢?参考如下:
- CMD ["nginx", "-g", "daemon off;"]
- stackoverflow.com/questions/2…
- hub.docker.com/_/nginx?tab…
FROM nginx
COPY dist /opt/workspace/app
COPY nginx.conf /etc/nginx/nginx.conf
复制代码
nginx.conf
- 重新设置了一个 server
- 设置上节的 /opt/workspace/app 为服务根目录
- 设置了 api 接口转发
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
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;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
# root /usr/share/nginx/html;
root /opt/workspace/app;
# index index.html index.htm;
index index.html;
}
location /api/{
proxy_pass http://111.229.229.157:9001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
}
复制代码
扩展:docker-compose & k8s
docker 中的方案介绍完了,docker-compose 和 k8s 怎么实现呢?
核心步骤都是一样的,只是涉及到的 docker-compose 和 k8s 语法不太一样,参考上面的步骤即可实现
多阶段构建
Dockerfile
m-company
是项目名字。把前端的编译构建和自定义 nginx 的过程结合起来。
- 以 builder 作为一个临时的用做前端编译构建的 docker stage
- 然后在自定义 nginx 阶段把 builder 阶段编译的内容复制到 nginx 需要的目录目录中
FROM node:alpine as builder
COPY . /opt/workspace/app/m-company
WORKDIR /opt/workspace/app/m-company/packages/front
RUN npm install
RUN npm run build
FROM nginx
WORKDIR /opt/workspace/app/m-company/nginx
COPY --from=builder /opt/workspace/app/m-company/packages/front/dist ./dist
COPY --from=builder /opt/workspace/app/m-company/nginx/nginx.conf /etc/nginx/nginx.conf
复制代码
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
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;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
# root /usr/share/nginx/html;
root /opt/workspace/app/m-company/nginx/dist;
# index index.html index.htm;
index index.html;
}
location /api/{
proxy_pass http://111.229.229.157:9001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
}
复制代码