这是docker在前端的使用实践篇,本文从一个小Demo入手,来学习一下基本的使用姿势。
拿一个场景来说,如果我们想要搭建一个网站,那我们常规操作需要这几部:
- 买一个云服务器,或者自己搞一个树莓派。
- 给服务器上装一个系统,无论是CentOS还是Ubuntu。
- 然后装nginx,如果需要数据库,那可能装一个套装。
- 前端在本地开发好项目,然后build出产物。
- 将产物同步到服务器上,然后配置一下nginx.conf,指定一个端口,配置上域名。
那就可以正常访问了。常规操作没有什么问题。
那我们现在用Docker来构建一个web的前端项目流程。
创建一个项目
因为这个过程和Docker没有什么关系,所以我们就直接用React来演示了,使用 create-react-app 创建项目,进入目录后使用 npm run build 命令构建出部署所需要的静态资源。
npx create-react-app docker-demo
cd docker-demo
npm run start
不出什么意外的话,你会看到这个页面。
本地能看到到是因为webpack-dev-server在本地给我们搭建了一个server,默认端口3000,这个大家都懂。
最终的产物需要build出来
npm run build
选一个服务器
ok,现在我们能在build文件夹中看到最终产物了。
如果我们在index.html上右键Open with Live Server(前提是你装了Live Server插件),当前插件会帮我们起一个服务,并在浏览器中打开页面。
但是页面白屏,原因是html文件中的src和href链接是 '/static'的写法,我们的Live Server是在docker-demo维度起的服务。所以我们将连接改成'./static' 就可以了。
但是这波操作显然我们是不愿意做的。且最终的产物其实是应该独立出docker-demo项目,独自运行的。
这种情况下,我们可以用Nginx起一个服务。Nginx是一款轻量级的 HTTP 服务器,具有很多非常优越的特性:轻量、高性能、并发能力强,用来部署静态页面很便捷。
既然使用docker,那我们就直接用docker的镜像来做就可以了。
我们先在docker-demo的项目中新建一个nginx.conf
,毕竟docker只解决环境,自己的配置还是要自己写的。
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" '
'statusbody_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 default_server;
server_name _;
# 重要的是location
location / {
root /usr/share/nginx/html;
index index.html ;
try_filesuri $uri/ /index.html;
}
}
}
来一个镜像配置
基础镜像这种东西,就和写代码一样,能C的就直接V了。
我们要在根目录创建 Dockerfile
文件来定制我们的镜像
- 使用 FROM 指令指定基础镜像,官方已经给我们准备好了 Nginx 的镜像
- 使用 LABEL 指令为构建的镜像设置作者信息
- 使用 ADD 指令将 build 文件夹下的所有文件拷贝至 Nginx 的根目录
- 使用 ADD 指令添加上一步准备好的 Nginx 配置文件
- 使用 EXPOSE 指令声明运行时容器提供的服务端口,暴露 80 端口
FROM nginx:latest
LABEL maintainer "英姿飒爽的翩翩少年"
# 这个和我们的nginx.conf是对应的。
ADD ./build/ /usr/share/nginx/html
# 将我们的配置文件放到nginx中。
ADD nginx.conf /etc/nginx/
EXPOSE 80
当然 /usr/share/nginx/html
这个路径可以自己定义。只要是docker和nginx的配置相同就行。
提醒一点:有的小朋友执行完docker的命令后就会去本地的 /usr/share/nginx/html
路径中去找,发现没有我们build的产物,会怀疑是不是我们的ADD命令有问题?
有这样的疑问是对docker的虚拟化还不了解。上篇文章中有说到,docker创建出的容器是和我们本地的环境完全隔离的。所以先想要查看文件得进入到docker的容器中查看,下面有进入的方式介绍。
构建一个镜像
这里我们使用 docker build
命令来进行构建
执行
docker build -t demo/nginx:v1 .
这个时候我们执行 docker images
会显示
REPOSITORY TAG IMAGE ID CREATED SIZE
demo/nginx v1 7ae06402eb54 4 minutes ago 142MB
如果你的vscode 中装了Docker的插件,也可以看到。
测试一下
docker run -d -p 8080:80 demo/nginx:v1
打开浏览器,访问 localhost:8080。出现如下页面表示工作正常,测试通过。
上面说到如果我们想进入容器内看一看,要怎么做。
首先 docker ps -a
查看一下当前启动了哪些容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5111127fb413 demo/nginx:v1 "/docker-entrypoint.…" 8 minutes ago Up 7 minutes 0.0.0.0:8080->80/tcp inspiring_rubin
拿到CONTAINER ID,然后执行 docker exec -it 5111127fb413 /bin/bash
这样我们就进入到当前容器中了,我们一直cd到 /usr/share/nginx/html 路径中,可以发现我们的build出来的产物。
命令行用起来还是比较麻烦,所以我们直接使用VSCode的插件 或者和是 Docker的客户端,用起来事倍功半。
这是我们一直在本地去做的。放到服务器上也是很容易的。服务器上装上docker。吧我们的Dockerfile和nginx.conf传上去,run一下就ok。
当然这只是一个简单的Demo,实际的业务我们要处理的东西还有很多,要写的Dockerfile也很长。这个要随业务灵活变动。
即使这样Docker依旧能很大程度上提升我们部署的效率,我们不需要自己部署nginx或其他的服务器。也不需要担心本地环境和线上环境的不同,只要Image相同,就是相同的。
总结
平时我们只做业务开发是很少会用到docker的,但是要涉及到的部署或者是运维的话,Docker是绕不开的为数不多的选择。Docker 为前端应用提供了一致的运行环境,带来了快速部署、回滚等特性。除此之外,还需要考虑容器化应用的部署,容器的编排、调度等问题,可以使用 Kubernetes 等容器管理平台。
文章评论