如何在Docker中运行ReactJS或者AngularJS
本教程将向我们展示如何在Docker容器中运行JavaScript前端。应用程序将由HTML和JS文件以及其他此类静态内容组成,因此无法自行提供服务。我们需要通过Web服务器为我们的应用程序提供服务。
没有Web服务器会理解我们的应用程序处理自己的路由。这意味着,我们必须以一种将其URI传递到登陆HTML文件(通常为index.html)的方式对其进行配置。
NGINX容器
启动和运行Angular或者React前端的最简单方法之一就是使用NGINX图像。该映像已预先配置并针对静态文件托管进行了优化。
docker pull nginx
处理路由
我们启动了应用程序,发现没有路由可用。所有URI都应该是根Web目录中的文件或者文件夹。 NGINX不了解Angular,React或者任何其他应用程序中的路由。
为了使NGINX正确处理我们的路由,我们需要指示它将所有URI请求传递到特定文件,例如我们的index.html。由于所有URI都将转发到index.html,因此这减轻了所有路由到我们的应用程序的负担。
要配置NGNX,我们需要获取nginx.conf文件的副本。为此,我们将需要运行NGINX容器,然后获取conf文件的副本。
docker -d nginx
使用启动时输出的容器ID的前几个字符,运行以下命令来复制nginx.conf文件。
docker exec -it <docker id> cp /etc/nginx/conf.d/default.conf .
现在,我们具有该配置的副本。在文本编辑器中打开配置。
vi default.conf
在配置文件中找到以下部分。
location / { root /usr/share/nginx/html; index index.html index.htm; }
然后将其修改为以下示例。
location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html?$args; }
我们的更改指示NGINX首先查找与请求的URI匹配的文件或者文件夹。如果都不存在,请将所有URI传递给index.html。
启动容器
要在本地计算机或者服务器上快速启动前端,只需运行容器即可。
容器本身将仅托管静态HTML文件。开始使用卷时,我们必须将前端文件添加到容器中。
docker run -d -p 80:80 -v /path/to/your/files:/use/share/nginx -v nginx.conf:/etc/nginx/conf.d/default.conf:ro -n myfrontend nginx
上面的命令将像服务器服务一样连续运行容器,将容器的端口80暴露在主机的端口80上,并将我们的静态文件安装到NGINX的默认Web根目录。它还将我们的自定义版本替换为default.conf并将文件置于只读模式。
建立影像
通过在启动时添加文件和设置来运行容器是可以的,但是这样会使保持环境一致变得困难。运行前端的任何服务器都应具有完全相同的配置。当我们开始修改代码或者NGINX设置时,一致性变得更加困难。
我们应该始终构建自己的映像的另一个原因是版本控制。对映像的每次更改都会有其自己的映像,可以对其进行审核或者回滚。
部署也被简化。
- 创建一个目录来存储Docker映像配置和文件。
mkdir ~/projects/myapp-docker
- 将自定义nginx.conf文件(已完成)复制到项目文件夹。
cp nginx.conf ~/projects/myapp-docker
- 转到新项目目录。
cd ~/projects/myapp-docker
- 创建一个新的Dockerfile。
touch Dockerfile
- 将Dockerfile打开到文本编辑器中。
vi Dockerfile
我们将基于NGINX的图像。这简化了许多需要完成的工作。将以下行添加到Docker文件中。
FROM nginx:latest
例如,某些应用程序需要设置环境变量来确定其是否正在生产中运行。我们可以通过在Dockerfile中添加ENV来进行设置。例如,我们将环境设置为生产环境,并为我们的应用程序禁用调试输出。正斜杠使我们可以创建一个具有多个条目的ENV命令。
ENV environment production \ debug false
静态文件需要找到进入图像的方式才能提供。将以下行添加到Dockerfile中,使其与应用程序的项目文件的位置匹配。它将文件和子目录添加到NGINX映像的默认NGINX文档根目录。
COPY /path/to/my/project /usr/share/nginx/html \ default.conf /etc/nginx/conf.d/default.conf
除非我们通过端口80公开它,否则将无法访问我们的Web应用程序。添加以下行以允许通过端口80的流量到达容器。
EXPOSE 80
放在一起,Dockerfile应该类似于以下示例。
FROM nginx:latest ENV environment production \ debug false COPY /path/to/my/project /usr/share/nginx/html / default.conf /etc/nginx/conf.d/default.conf EXPOSE 80
如果没有创建Dockerfile,我们将开始构建映像。每当我们构建映像时,至少都需要一个名称。一个可选的但建议的步骤是也向图像名称添加唯一标记,例如版本号。
在以下示例中,我们将构建一个名为myapp的图像,并为其赋予标签1.0.0,以匹配我们应用程序的版本。
docker build -n myapp:1.0.0 .
每次发布应用程序的版本时,还应该创建一个匹配的映像。将其添加到生产构建脚本中以消除手动步骤可能是有益的。
运行React或者Angular容器
我们拥有我们的形象,现在该发布它了。映像所需的所有内容均已配置,因此运行我们的容器就像启动它一样简单。
docker run -d -p 80:80 myapp:1.0.0
启动容器后,养成验证其实际启动并正在运行的习惯。我们可以使用ps docker命令检查容器的状态。
docker ps
生产Docker映像
默认的NGINX映像基于Debian9. 在将应用程序复制到该映像之前,这是一个相当大的映像。对于那些想要尽可能瘦的人,有NGINX容器的Linux Alpine版本。让我们比较大小。
REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ae513a47849c 2 weeks ago 109MB nginx alpine ebe2c7c61055 5 weeks ago 18MB
马上,我们会看到标准NGINX图像和Alpine版本的尺寸大大减小。后者要小83%。较小的映像使存储管理更加容易。我们可能每天(可能每小时)部署多个生产版本。 Docker是一个ho积者,因为它不会删除不需要的容器。
每个运行的容器都保存在磁盘上,不仅消耗宝贵的存储空间,而且会使存储混乱。我们可以通过切换到较小的基本映像来减少存储消耗问题。
具有较小的图像也意味着我们可以保留更长的构建历史。如果我们需要在执行每小时构建的环境中紧急回滚到两周前发布的映像,这可能会很有用。
让我们更新Dockerfile以使用NGINX Alpine映像。
FROM nginx:alphine ENV environment production \ debug false COPY /path/to/my/project /usr/share/nginx/html / default.conf /etc/nginx/conf.d/default.conf EXPOSE 80
最后,让我们为Alpine版本构建一个新映像。
docker build -n myapp:1.0.0 .
如果我们已经有一个名为myapp:1.0.0的映像,则新版本将覆盖它。无需删除我们旧的基于Debian的NGINX映像。