In this post you'll learn how to configure a development environment with live-reload enabled. This will allow you to convert a legacy application so it uses Docker, Docker volumes, and docker-compose.
在本文中,您将学习如何配置启用实时重载的开发环境。 这将允许您转换旧版应用程序,使其使用Docker,Docker卷和docker-compose。
Some developers turn up their noses when talking about using Docker for their development environment. They say that Docker isn't good for development because it always needs to rebuild the entire image to reflect all new modifications. This makes it unproductive and slow.
一些开发人员在谈论将Docker用于其开发环境时大为惊讶。 他们说Docker不利于开发,因为Docker始终需要重建整个映像以反映所有新修改。 这使其徒劳又缓慢。
In this article, our goal is to tackle this mindset by demonstrating how simple configurations can result in many benefits such as a reliable environment over production and development environments.
在本文中,我们的目标是通过演示简单的配置如何带来许多好处(例如在生产和开发环境中提供可靠的环境)来解决这种思想。
By the end of this post you will have learned how to:
在本文结束时,您将学习如何:
- Convert a legacy application to run within a Docker container; 转换旧版应用程序以在Docker容器中运行;
- Enable dependency caching on Node.js modules; 在Node.js模块上启用依赖项缓存;
- Enable live-reload by using docker volumes; 使用Docker卷启用实时重新加载;
- Aggregate all services within docker-compose. 聚合docker-compose中的所有服务。
要求 (Requirements)
In the next steps, you'll clone an existing project to execute all examples in this article. Before starting to code make sure you have the following tools installed on your machine:
在接下来的步骤中,您将克隆一个现有项目以执行本文中的所有示例。 在开始编码之前,请确保已在计算机上安装以下工具:
为什么要使用docker? (Why use docker?)
More and more cutting-edge technologies are being released for the internet all the time. They're stable, and they're fun to develop and release, but they're not predictable when working over different environments. So developers created Docker to help reduce the chances of possible errors.
越来越多的尖端技术一直在为互联网发布。 它们很稳定,开发和发布都很有趣,但是在不同环境下工作时它们是不可预测的。 因此,开发人员创建了Docker以帮助减少可能出现错误的机会。
Docker is one of my favorite tools that I work with every day on desktop, web, and IoT apps. It has given me the power to not only move applications through different environments, but also to keep my local environment as clean as possible.
Docker是我每天在桌面,Web和IoT应用程序上最喜欢使用的工具之一。 它不仅使我能够在不同的环境中移动应用程序,还使我的本地环境尽可能保持清洁。
Developers working with cutting-edge technologies are always working with something new. But what about legacy applications? Should we just rewrite everything with new tech? I know this is not as simple as it seems. We should work on new stuff, but also make improvements to existing applications.
使用尖端技术的开发人员始终在处理新事物。 但是遗留应用程序呢? 我们是否应该使用新技术重写所有内容? 我知道这并不像看起来那么简单。 我们应该研究新事物,同时还要对现有应用程序进行改进。
Let's say you have decided to move from Windows Servers to Unix servers. How would you do it? Do you know every dependency your app requires to work?
假设您已决定从Windows Server迁移到Unix服务器。 你会怎么做? 您知道您的应用程序需要工作的每个依赖项吗?
开发环境应该是什么样? (What should a development environment look like?)
Developers have always tried to be more productive by adding plugins, boilerplates, and codebases on their editors/IDEs/terminals. The best environment in my opinion should be:
开发人员一直试图通过在其编辑器/ IDE /终端上添加插件,样板和代码库来提高生产力。 我认为最好的环境应该是:
- Easy to run and test; 易于运行和测试;
- Environment agnostic; 与环境无关;
- Fast to evaluate modifications; 快速评估修改;
- Easy to replicate on any machine. 易于在任何机器上复制。
Following these principles, we'll configure an application over the next sections of this article. Also, if you've never heard about live-reload (or hot reload), it is a feature that watches for changes in your code and restarts the server if needed. So you don't need to go back and forth, restarting your app or even rebuilding the system.
遵循这些原则,我们将在本文的下一部分中配置一个应用程序。 另外,如果您从未听说过实时重装(或热重装),则此功能可监视代码中的更改并在需要时重新启动服务器。 因此,您无需来回移动,重新启动应用程序甚至重建系统。
入门 (Getting started)
First, you'll need to have an empty folder called post-docker-livereload
which you'll use as a workspace. Go to the Github repository and clone it on your post-docker-live-reload folder.
首先,您需要有一个名为post-docker-livereload
的空文件夹,它将用作工作区。 转到Github存储库并将其克隆到您的docker-live-reload文件夹中。
Secondly, let's analyse what the application requires. If you take a look at the README.md file, there are a few instructions demonstrating how to run this app as shown in the image below:
其次,让我们分析应用程序的需求。 如果您查看README.md文件,则有一些说明,说明如何运行此应用程序,如下图所示:
It requires Node.js version 10 or higher and MongoDB. Instead of installing MongoDB on your local environment machine, you'll install it using Docker. You'll also expose it on localhost:27017 so applications that are not running through Docker can access it without knowing the internal Docker IP address.
它需要Node.js版本10或更高版本以及MongoDB。 不用在本地环境机器上安装MongoDB,而是使用Docker安装它。 您还将在localhost:27017上公开它,以便未通过Docker运行的应用程序可以在不知道内部Docker IP地址的情况下访问它。
Copy the command below and paste it in your terminal:
复制下面的命令并将其粘贴到您的终端中:
docker run --name mongodb -p 27017:27017 -d mongo:4
Using the command above, it'll download and run the MongoDB instance. Notice that if you already have an instance with this name it'll throw an error about invalid name.
使用上面的命令,它将下载并运行MongoDB 实例。 请注意,如果您已经有一个使用此名称的实例,它将引发有关无效名称的错误。
If you see the error, run docker rm mongodb
and it will remove any previous instance so you can run the docker run command again.
如果看到错误,请运行docker rm mongodb
,它将删除任何先前的实例,因此您可以再次运行docker run命令。
挖掘应用程序 (Digging into the application)
The README.md file says that you need a MongoDB instance running before starting your app, along with Node.js.
README.md文件表明,在启动您的应用之前,您需要运行一个MongoDB实例以及Node.js。
If you have Node.js installed, go to the nodejs-with-mongodb-api-example
folder and run the following commands:
如果已安装Node.js,请转到nodejs-with-mongodb-api-example
文件夹并运行以下命令:
npm i
npm run build
npm start
After running these commands, you can go to a browser on http://localhost:3000 and see the application running as shown in the image below:
运行这些命令后,您可以转到http:// localhost:3000上的浏览器,并看到应用程序正在运行,如下图所示:
Keep in mind that the app already has a command to enable live reload which is npm run dev:watch
. The pipeline should reflect the following steps:
请记住,该应用程序已经具有启用实时重新加载的命令,这是npm run dev:watch
。 管道应反映以下步骤:
- Developer changes Typescript files; 开发人员更改Typescript文件;
- Typescript transpiles files to Javascript; Typescript将文件转换为Javascript;
- Server notices changes to Javascript and restarts the Node.js server. 服务器注意到Javascript的更改,并重新启动Node.js服务器。
So mirroring files to Docker containers will reflect all changes in the container. The npm run build:watch
from the application will catch the changes and generate output files in the lib folder so the npm run dev:run
will restart the server every time it has been triggered.
因此,将文件镜像到Docker容器将反映容器中的所有更改。 应用程序中的npm run build:watch
将捕获更改并在lib中生成输出文件 文件夹,因此npm run dev:run
将在每次触发服务器时重新启动服务器。
Docker化应用程序 (Dockerizing applications)
If Docker is a completely new world to you, don't be afraid! You will configure it from scratch. You'll need to create a few files to start:
如果Docker对您来说是一个全新的世界,请不要害怕! 您将从头开始配置它。 您需要创建一些文件才能开始:
Dockerfile
- a receipt file that lists how to install and run your app;Dockerfile
一个收据文件,列出了如何安装和运行您的应用程序;.dockerignore
- a file that lists what file(s) won't go within the Docker container instance..dockerignore
一个列出Docker容器实例中不会包含哪些文件的文件
创建Dockerfile (Creating the Dockerfile)
The Dockerfile is the key concept here. There you specify the steps and dependencies to prepare and run the application. As long as you have read the README.md file, it will be easy to implement the receipt file.
Dockerfile是这里的关键概念。 在此指定准备和运行应用程序的步骤和相关性。 只要您已阅读README.md文件,将很容易实现收据文件。
I'm going to put the whole file below and dig into it later. In your nodejs-with-mongodb-api-example
folder create a Dockerfile
file and paste the code below:
我将把整个文件放在下面,并在以后进行深入研究。 在您的nodejs-with-mongodb-api-example
文件夹中创建一个Dockerfile
文件并粘贴以下代码:
FROM node:14-alpine
WORKDIR /src
ADD package.json /src
RUN npm i --silent
ADD . /src
RUN npm run build
CMD npm start
What's happening there?
那里发生了什么事?
- On line 1 - It uses as its image base Node.js 14 - alpine version; 第1行-使用Node.js 14作为其图像基础-高山版本;
- From lines 2 to 4 - It copies and installs Node.js dependencies from host to container. Note that the order there is important. Adding package.json to the src folder before restoring dependencies will cache it and prevent it from installing packages every time you need to build your image; 从第2行到第4行-从主机到容器复制并安装Node.js依赖项。 注意那里的顺序很重要。 在还原依赖关系之前将package.json添加到src文件夹中将对其进行缓存,并阻止它在每次需要构建映像时安装软件包;
- From lines 6 to 7 - It runs commands for the compilation process and then for starting the program as mentioned in the README.md file. 从第6到7行-如README.md文件中所述,它运行用于编译过程然后启动程序的命令。
使用.dockerignore忽略不必要的文件 (Ignoring unnecessary files with .dockerignore)
Also, I'm working on an OSX-based system and the Docker container will run on a Linux Alpine-based system. When you run npm install
it will restore dependencies for specific environments.
另外,我正在基于OSX的系统上工作,而Docker容器将在基于Linux Alpine的系统上运行。 当您运行npm install
它将恢复特定环境的依赖关系。
You will now create a file to ignore the generated code from your local machine such as node_modules and lib. So when you copy all files from the current directory to the container it won't get invalid package versions.
现在,您将创建一个文件,以忽略从本地计算机生成的代码,例如node_modules和lib 。 因此,当您将所有文件从当前目录复制到容器时,它不会获得无效的软件包版本。
In the nodejs-with-mongodb-api-example
folder create a .dockerignore
file and paste the code below:
在nodejs-with-mongodb-api-example
文件夹中创建一个.dockerignore
文件并粘贴以下代码:
node_modules/
lib/
构建Docker映像 (Building the docker image)
I prefer running this app from the rootFolder. Go back to the post-docker-live-reload
folder and run the following commands to prepare an image for further use:
我更喜欢从rootFolder运行此应用程序。 返回post-docker-live-reload
文件夹并运行以下命令以准备映像以备将来使用:
docker build -t app nodejs-with-mongodb-api-example
Notice that the command above uses the -t
flag to tell you the image name and, right after that, the folder which contains the Dockerfile
file.
请注意,上面的命令使用-t
标志来告诉您映像名称,以及Dockerfile
是包含Dockerfile
文件的文件夹。
处理卷 (Working with volumes)
Before running the app, let's do a few hacks to improve our experience in the Docker containers.
在运行该应用程序之前,让我们做一些修改以改善我们在Docker容器中的体验。
Docker volumes is a feature to mirror files through your local machine and Docker environment. You can also share volumes over containers and reuse them to cache dependencies.
Docker卷是一项通过本地计算机和Docker环境镜像文件的功能。 您还可以在容器上共享卷,然后重复使用它们以缓存依赖项。
Your goal is to watch any changes on local .ts
files and mirror those changes in the container. Even though the files and the node_modules
folder are in the same path.
您的目标是观察本地.ts
文件上的所有更改,并在容器中镜像这些更改。 即使文件和node_modules
文件夹位于同一路径中。
Do you remember when I said that the dependencies in each operating system would be different? To make sure our local environment won't affect the Docker environment when mirroring files, we'll isolate the container's node_modules
folder on a distinct volume.
您还记得我说过每个操作系统中的依赖关系会有所不同吗? 为了确保我们的本地环境在镜像文件时不会影响Docker环境,我们将容器的node_modules
文件夹隔离在不同的卷上。
Consequently, when creating the node_modules
folder on the container, it won't create the folder on local machine environment. Run the command below in your terminal to create it:
因此,在容器上创建node_modules
文件夹时,它将不会在本地计算机环境上创建该文件夹。 在终端中运行以下命令以创建它:
docker volume create --name nodemodules
运行并启用实时重新加载 (Running and enabling live-reload)
As you know, the npm run dev:watch
specified in the README.md shows how to enable live-reload. The problem is that you're coding on a local machine and it must reflect directly your container.
如您所知,README.md中指定的npm run dev:watch
显示了如何启用实时重载。 问题是您在本地计算机上编码,它必须直接反映您的容器。
By running the following commands you will link your local environment with the Docker container so any change in
will affect the container's nodejs-with-mongodb-api-example
src
folder.
通过运行以下命令,您会将您的本地环境链接到Docker容器,这样
任何更改都会影响该容器的nodejs-with-mongodb-api-example
src
文件夹。
docker run \
--name app \
--link mongodb \
-e MONGO_URL=mongodb \
-e PORT=4000 \
-p 4000:4000 \
-v `pwd`/nodejs-with-mongodb-api-example:/src \
-v nodemodules:/src/node_modules \
app npm run dev:watch
Let's dig into what's happening there:
让我们深入研究那里发生的事情:
--link
is giving permission to the app to access the MongoDB instance;--link
授予应用访问MongoDB实例的权限;-e
- is the environment variables. As mentioned in the README.md file you can specify the MongoDB connection string you want to connect to by overriding theMONGO_URL
variable. Override thePORT
variable if you want to run it on a different port. Note that the valuemongodb
is the same name we used to create our MongoDB instance in the previous sections. This value is also an alias for the internal MongoDB instance's IP;-e
是环境变量。 如README.md文件中所述 您可以通过覆盖MONGO_URL
变量来指定要连接的MongoDB连接字符串。 如果要在其他端口上运行,请覆盖PORT
变量。 请注意,值mongodb
与我们在前面的部分中用于创建MongoDB实例的名称相同。 此值也是内部MongoDB实例IP的别名;-v
- maps the current directory to the Docker container by using a virtual volume. Using thepwd
command you can get the absolute path for your current working directory and then the folder you want to mirror on the Docker container. There's the:/src
. Thesrc
path is theWORKDIR
instruction defined onDockerfile
so we mirror the local folder to the Docker container's src;-v
-通过使用虚拟卷映射当前目录到多克尔容器。 使用pwd
命令,您可以获取当前工作目录的绝对路径,然后获取要在Docker容器上镜像的文件夹。 有:/src
。src
路径是在Dockerfile
定义的WORKDIR
指令,因此我们将本地文件夹镜像到Docker容器的src。-v
- the second volume there will mirror the individual volume we created on the container'snode_modules
folder;-v
-第二卷将有反映我们在容器的创建单个卷node_modules
文件夹;app
- the image name;app
图像名称;npm run dev:watch
- this last command will override theCMD
instruction from theDockerfile
.npm run dev:watch
Dockerfile
这最后一个命令将覆盖Dockerfile
的CMD
指令。
After running the command below, you can trigger the browser after changing the local index.ts
file to see the results. The video below demonstrates these steps in practice:
运行以下命令后,可以在更改本地index.ts
文件后触发浏览器以查看结果。 以下视频演示了实践中的这些步骤:
结语 (Wrapping up)
You know that working with shell commands works. But is not that common to use them here, and it's not productive for running all those commands, building images, and managing instances by hand. So compose it!
您知道使用shell命令是可行的。 但是在这里使用它们并不常见,并且无法手动运行所有这些命令,构建映像和管理实例。 组成吧!
Docker compose is a way to simplify the aggregation and linking of services. You can specify the databases, logs, application, volumes, networks, and so on.
Docker compose是一种简化服务聚合和链接的方法。 您可以指定数据库,日志,应用程序,卷,网络等。
First, you need to remove all active instances to avoid conflict on exposed ports. Run the following commands on your terminal to remove volumes, services and containers:
首先,您需要删除所有活动实例,以避免在暴露的端口上发生冲突。 在终端上运行以下命令以删除卷,服务和容器:
docker rm app
docker volume rm nodemodules
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
docker-compose文件 (The docker-compose file)
Create a docker-compose.yml
file on your post-docker-livereload
folder using the data below:
使用以下数据在post-docker-livereload
文件夹上创建docker-compose.yml
post-docker-livereload
文件:
version: '3'
services:
mongodb:
image: mongo:4
ports:
- 27017:27017
app:
build: nodejs-with-mongodb-api-example
command: npm run dev:watch
ports:
- 4000:4000
environment:
MONGO_URL: mongodb
PORT: 4000
volumes:
- ./nodejs-with-mongodb-api-example:/src/
- nodemodules:/src/node_modules
links:
- mongodb
depends_on:
- mongodb
volumes:
nodemodules: {}
The file above specifies resources by sections. Notice that you have links
and depends_on
sections there. The links field is the same flag you've used in your shell command. The depends_on
will make sure that the MongoDB is a dependency for running your app. It'll run the MongoDB before your app like magic!
上面的文件按部分指定资源。 请注意,那里有links
和depends_on
部分。 links字段与您在shell命令中使用的标志相同。 depends_on
将确保MongoDB是运行您的应用程序的依赖项。 它将像魔术般在您的应用程序之前运行MongoDB!
Going back to your terminal, to start all services and build the Docker image and create volumes and link services run the following command:
回到您的终端,启动所有服务并构建Docker映像并创建卷和链接服务,运行以下命令:
docker-compose up --build
If you need to remove all services created before by that Dockerfile
you can also run docker-compose down
.
如果您需要删除该Dockerfile
之前创建的所有服务,还可以运行Dockerfile
docker-compose down
。
Docker是您的朋友! (Docker is your friend!)
That's right, my friend. Docker can help you prevent many possible errors before they happen. You can use it for front and back end applications. Even for IoT when you need to control hardware, you can specify policies for using it.
是的,我的朋友。 Docker可以帮助您防止许多可能的错误发生。 您可以将其用于前端和后端应用程序。 即使对于需要控制硬件的物联网,也可以指定使用策略。
As your next steps, I highly recommend that you take a look at container orchestrators such as Kubernetes and Docker swarm. They could improve even more your existing applications and help you go to the next level.
作为下一步,我强烈建议您看一下容器编排器,例如Kubernetes和Docker swarm。 他们可以改善您现有的应用程序,并帮助您进入新的水平。
感谢您的阅读 (Thank you for reading)
I really appreciate the time we spent together. I hope this content will be more than just text. I hope it will help make you a better thinker and also a better programmer. Follow me on Twitter and check out my personal blog where I share all my valuable content.
我真的很感谢我们一起度过的时间。 我希望这些内容将不仅仅是文字。 我希望它能帮助您成为一个更好的思想家和一个更好的程序员。 在Twitter上关注我,并查看我的个人博客 ,我在其中分享了我所有的宝贵内容。
See ya! 🍻
拜拜! 🍻
翻译自: https://www.freecodecamp.org/news/how-to-enable-live-reload-on-docker-based-applications/