本文不教如何安装docker,默认已安装好docker。这是我的docker版本,在我本地安装的。
docker 基本操作
docker的命令远远不止这些,本文只讲需要用到的。
docker pull 拉取nginx镜像
如果你之前用nginx部署过前端项目的话,用docker部署你就会发现更简单。
docker pull nginx
等待pull完成,pull成功之后,可以用docker images查看一下
可以看到nginx已经成功下载了。
docker run 启动nginx镜像
docker run -d -p 80:80 --name nginx nginx
-d: 让容器后台运行(detached mode)-p 80:80: 前面80是宿主机的端口号,后面80是容器的端口号,意思是将宿主机的80端口映射到容器的80端口。当访问宿主机的80端口时,请求会被映射到容器内的Nginx服务的80端口,从而能够访问到Nginx服务。--name nginx: 设置容器的名称,方便后续对该容器进行管理操作,例如停止、启动或删除容器时,可以通过这个名称来指定操作的容器对象,名字随便取,叫什么都可以。nginx: 镜像名称
启动之后,终端会输出对应的容器id,说明已经启动成功。也可以用
docker ps查看一下
docker ps 查看运行中的容器
可以看到,有一条
nginx的容器正在运行,这个容器的id是84开头,正是我们刚刚执行docker run返回的那个容器id。
打开浏览器,输入localhost,可以看到下面的默认页面,恭喜你,已经成功用docker启动nginx了。
http端口号默认80,所以可以省略端口号,如果你映射的是其他端口号,记得带上端口号
如果你是在本地电脑上安装的docker,搭配docker官方提供的Docker Desktop桌面端,使用起来更方便。上面所有的命令,在Docker Desktop里面都有对应的可视化操作。
docker stop
docker stop <容器名/容器ID>
这里要注意是容器名称,不是镜像名称,就是前面我们执行docker run命令后面带的参数--name nginx的nginx。
执行docker stop nginx,可以看到返回了容器的名称。然后docker ps再查看一下运行的容器,发现并没有nginx容器里。
再刷新一下浏览器看看
部署
创建项目
npm create vite@latest
依次执行
cd docker-fe-demo
npm install
run run dev
在App.tsx里面随便写一点代码,保存一下。
function App() {
return <>hello sens</>;
}
export default App;
页面正常渲染了
编写Dockerfile--多阶段构建
在项目根目录新建一个Dockerfile和docker.nginx.conf文件。
Dockerfile是固定名字,类似于webpack.config.js,docker.nginx.conf自己随便取,但是要保证.conf结尾
我的做法是把nginx的conf配置文件暴露出来,放到前端,方便修改,最后copy进去,丢到nginx对应配置文件的地方。当然,你也可以不放到前端,写死在nginx里面也行。
# build 阶段
FROM node:18-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm config set registry https://registry.npmmirror.com/
RUN npm install
COPY . .
RUN npm run build
# production 阶段
FROM nginx:stable as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY --from=build-stage /app/docker.nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
解释一下这份配置文件,把镜像分成了两个阶段(FROM了两次),build阶段和production阶段。最终镜像产物就是最后一个FROM的镜像,这里最后FROM了nginx,相当于生成了一份nginx的镜像。
build阶段
WORKDIR /app: 设置容器内的工作目录为/app,后续的操作(如复制文件、运行命令等)都将在这个目录下进行。COPY package*.json ./: 将主机上与package相关的json文件(通常是package.json和package-lock.json)复制到容器内的/app目录下。这一步是为了先安装项目依赖RUN npm config set registry https://registry.npmmirror.com/: 设置npm淘宝源RUN npm install: 执行npm installCOPY . .:将(主机)当前目录下的所有文件复制到容器内的/app目录下。RUN npm run build:在容器内运行npm run build命令,构建项目(通常是将源代码编译、打包等操作)。
build阶段完成之后,我们可以得到打包之后的dist文件了,后面只要把这份文件,丢给nginx即可。
production阶段
COPY --from=build-stage /app/dist /usr/share/nginx/html: 将build-stage阶段构建的/app/dist复制到/usr/share/nginx/html目录(为什么是/usr/share/nginx/html目录呢?后面说)COPY --from=build-stage /app/docker.nginx.conf /etc/nginx/conf.d/default.conf: 同理,将build-stage阶段构建的/app/docker.nginx.conf复制到/etc/nginx/conf.d/default.conf。EXPOSE 80:容器暴露80端口。CMD ["nginx", "-g", "daemon off;"]:启动nginx服务器,并关闭守护进程模式,以便容器可以持续运行并提供服务。
上面多了两个很陌生的文件目录地址,/usr/share/nginx/html和/etc/nginx/conf.d/default.conf。了解nginx的朋友应该知道这是什么意思。
一开始我们已经pull nginx镜像,并且将nginx运行起来,现在让我们进入到nginx容器里面。
docker exec -it nginx /bin/bash
这里也可以看到,是我们之前
84开头的nginx容器。
然后执行:
cat /etc/nginx/nginx.conf
打印一下nginx的配置信息。
可以看到,有这样的一项配置,
include /etc/nginx/conf.d/*.conf;它的意思是/etc/nginx/conf.d/目录下所有以.conf为后缀的配置文件都会引入到主配置文件中使其生效。
那让我们去/etc/nginx/conf.d/目录看看。
cd /etc/nginx/conf.d/
ls
cat default.conf
圈中的意思是指定root(根)目录是
/usr/share/nginx/html,当收到一个请求的时候,就会去指定的root目录里面找对应的index文件。
再进入到/usr/share/nginx/html里面看看:
cd /usr/share/nginx/html
ls
cat index.html
这不正是我们开头运行nginx镜像,访问localhost显示出来的页面内容吗?
所以,我们只要把打包之后的dist文件丢到/usr/share/nginx/html里面就行。
你也可以修改
conf配置文件,指定root的值是任何目录,这里我选择的是不指定,而是把我的dist文件copy丢进去。
编写nginx配置文件
docker.nginx.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
特别注意的是 try_files $uri $uri/ /index.html; 这是实现前端路由的关键。我们都知道,history路由,页面刷新的时候,是会请求服务器地址的。这句话的意思是,请求过来,会尝试在root目录下面寻找当前的uri,如果没有找到就找uri/,如果还没有找到,就返回index.html。只有返回了index.html,才能走到前端路由逻辑。
docker build 构建镜像
docker build -t docker-fe-demo .
-t:指定构建出来的镜像的名称和标签。我这里没有指定,tag默认就是latest,你也可以-t docker-fe-demo:sens,这个镜像的标签就是sens。.:Docker将会在当前目录下寻找Dockerfile文件并执行构建,就是前面设置的WORKDIR
docker run 启动镜像
docker run -d -p 80:80 --name docker-fe-demo docker-fe-demo
注意端口不要被其他程序占用,再次访问localhost,可以看到,成功部署了。
总结
大致流程如下:
如果你是在云服务器上,比如阿里云、腾讯云之类,要注意打开安全组和防火墙的端口号,不然无法访问。