思情话意 發表於 2025-12-12 09:22:48

Docker容器化Node.js应用操作教程

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">从零开始:用Docker容器化你的第一个Node.js应用</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">1. 引言</a></li><li><a href="#_lab2_0_1">2. 项目准备</a></li><ul class="third_class_ul"><li><a href="#_label3_0_1_0">2.1. 应用代码 (index.js)</a></li><li><a href="#_label3_0_1_1">2.2. Docker镜像定义文件 (Dockerfile)</a></li></ul><li><a href="#_lab2_0_2">3. 构建Docker镜像</a></li><ul class="third_class_ul"><li><a href="#_label3_0_2_2">3.1. 构建命令</a></li><li><a href="#_label3_0_2_3">3.2. 构建日志</a></li><li><a href="#_label3_0_2_4">3.3. 构建过程解析</a></li></ul><li><a href="#_lab2_0_3">4. 查看本地镜像</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_0_4">5. 运行容器</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_0_5">6. 查看容器</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_0_6">7. 实践总结</a></li><ul class="third_class_ul"></ul></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>从零开始:用Docker容器化你的第一个Node.js应用</h2>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>1. 引言</h3>
<p>在现代软件开发中,Docker已成为不可或缺的工具。它通过容器化技术,将应用及其依赖环境打包在一起,实现了&ldquo;一次构建,处处运行&rdquo;的梦想。今天,我将带大家完成一个完整的Docker实践:容器化一个简单的Node.js应用,从编写代码到运行容器,一步步掌握Docker的核心操作。</p>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>2. 项目准备</h3>
<p>首先,我们创建一个简单的Node.js项目,仅包含两个文件:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121209190525.png" /></p>
<p class="maodian"><a name="_label3_0_1_0"></a></p><h4>2.1. 应用代码 (index.js)</h4>
<div class="jb51code"><pre class="brush:js;">console.log("你好,世界!")</pre></div>
<p>这是一个最简单的Node.js程序,输出一句问候语。</p>
<p class="maodian"><a name="_label3_0_1_1"></a></p><h4>2.2. Docker镜像定义文件 (Dockerfile)</h4>
<p>让我们解析一下这个Dockerfile:</p>
<ul><li><strong>FROM node:14-alpine</strong>:指定基础镜像为Node.js 14的Alpine Linux版本,这是一个轻量级的Linux发行版</li><li><strong>COPY index.js /index.js</strong>:将本地的index.js文件复制到容器内的根目录</li><li><strong>CMD node /index.js</strong>:设置容器启动时默认执行的命令</li></ul>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>3. 构建Docker镜像</h3>
<p>有了Dockerfile,我们就可以创建自定义的Docker镜像了。</p>
<p class="maodian"><a name="_label3_0_2_2"></a></p><h4>3.1. 构建命令</h4>
<div class="jb51code"><pre class="brush:bash;">docker build -t hello-docker .
</pre></div>
<p>这个命令的含义是:</p>
<ul><li><code>docker build</code>:启动镜像构建过程</li><li><code>-t hello-docker</code>:为镜像打上标签(名称),便于后续引用</li><li><code>.</code>:使用当前目录作为构建上下文,Docker会查找当前目录下的Dockerfile</li></ul>
<p class="maodian"><a name="_label3_0_2_3"></a></p><h4>3.2. 构建日志</h4>
<div class="jb51code"><pre class="brush:js;">PS E:\hello-world\hello-docker&gt; docker build -t hello-docker .
[+] Building 369.5s (7/7) FINISHED                                                                            docker:desktop-linux
=&gt; load build definition from Dockerfile                                                                        0.1s
=&gt; =&gt; transferring dockerfile: 103B                                                                                          0.0s
=&gt; load metadata for docker.io/library/node:14-alpine                                                         263.8s
=&gt; load .dockerignore                                                                                             0.0s
=&gt; =&gt; transferring context: 2B                                                                                             0.0s
=&gt; load build context                                                                                             0.1s
=&gt; =&gt; transferring context: 29B                                                                                              0.0s
=&gt; FROM docker.io/library/node:14-alpine@sha256:434215b487a329c9e867202ff89e704d3a75e554822e07f3e0c0f9e606121b33   103.1s
=&gt; =&gt; resolve docker.io/library/node:14-alpine@sha256:434215b487a329c9e867202ff89e704d3a75e554822e07f3e0c0f9e606121b33       0.1s
=&gt; =&gt; sha256:434215b487a329c9e867202ff89e704d3a75e554822e07f3e0c0f9e606121b33 1.43kB / 1.43kB                              0.0s
=&gt; =&gt; sha256:4e84c956cd276af9ed14a8b2939a734364c2b0042485e90e1b97175e73dfd548 1.16kB / 1.16kB                              0.0s
=&gt; =&gt; sha256:0dac3dc27b1ad570e6c3a7f7cd29e88e7130ff0cad31b2ec5a0f222fbe971bdb 6.44kB / 6.44kB                              0.0s
=&gt; =&gt; sha256:0dac3dc27b1ad570e6c3a7f7cd29e88e7130ff0cad31b2ec5a0f222fbe971bdb 6.44kB / 6.44kB                              0.0s
=&gt; =&gt; sha256:f56be85fc22e46face30e2c3de3f7fe7c15f8fd7c4e5add29d7f64b87abdaa09 3.37MB / 3.37MB                               63.4s
=&gt; =&gt; sha256:8f665685b215c7daf9164545f1bbdd74d800af77d0d267db31fe0345c0c8fb8b 37.17MB / 37.17MB                           90.6s
=&gt; =&gt; sha256:e5fca6c395a62ec277102af9e5283f6edb43b3e4f20f798e3ce7e425be226ba6 2.37MB / 2.37MB                               52.7s
=&gt; =&gt; sha256:561cb69653d56a9725be56e02128e4e96fb434a8b4b4decf2bdeb479a225feaf 448B / 448B                                 95.7s
=&gt; =&gt; extracting sha256:f56be85fc22e46face30e2c3de3f7fe7c15f8fd7c4e5add29d7f64b87abdaa09                                     0.6s
=&gt; =&gt; extracting sha256:8f665685b215c7daf9164545f1bbdd74d800af77d0d267db31fe0345c0c8fb8b                                    11.2s
=&gt; =&gt; extracting sha256:e5fca6c395a62ec277102af9e5283f6edb43b3e4f20f798e3ce7e425be226ba6                                     0.3s
=&gt; =&gt; extracting sha256:561cb69653d56a9725be56e02128e4e96fb434a8b4b4decf2bdeb479a225feaf                                     0.0s
=&gt; COPY index.js /index.js                                                                                             2.0s
=&gt; exporting to image                                                                                                      0.2s
=&gt; =&gt; exporting layers                                                                                                       0.1s
=&gt; =&gt; writing image sha256:be987f77136525684c13002b3a8d43cc6cd4d62986f7997128b51946aad6d03c                                  0.0s
=&gt; =&gt; naming to docker.io/library/hello-docker                                                                               0.0s
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/pnwg2u6n5xocvatlj87a6v6fj
1 warning found (use docker --debug to expand):
- JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals (line 3)</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121209190522.jpg" /></p>
<p class="maodian"><a name="_label3_0_2_4"></a></p><h4>3.3. 构建过程解析</h4>
<ol><li>Docker首先下载基础镜像<code>node:14-alpine</code>(如果本地不存在)</li><li>然后执行COPY指令,将index.js文件复制到镜像中</li><li>最后设置默认的启动命令</li><li>构建完成后,生成了一个ID为<code>be987f771365</code>的新镜像</li></ol>
<p>这里Docker给出了一个有用的警告:建议使用JSON格式的CMD指令来避免信号处理问题。虽然不影响当前使用,但在生产环境中需要注意这一点。</p>
<p class="maodian"><a name="_lab2_0_3"></a></p><h3>4. 查看本地镜像</h3>
<p>构建完成后,我们可以查看本地已有的Docker镜像:</p>
<div class="jb51code"><pre class="brush:bash;">docker images
</pre></div>
<p>日志输出:</p>
<div class="jb51code"><pre class="brush:plain;">PS E:\hello-world\hello-docker&gt; docker images
REPOSITORY                     TAG       IMAGE ID       CREATED         SIZE
hello-docker                     latest    be987f771365   8 minutes ago   119MB
hello-world                      latest    74cc54e27dc4   10 months ago   10.1kB
hub.oepkgs.net/openeuler/nginx   &lt;none&gt;    1d992e662bfc   13 months ago   747MB</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121209190517.png" /></p>
<p>输出显示我们刚刚创建的<code>hello-docker</code>镜像大小为119MB,相比基础镜像已经很小了。同时可以看到系统中还有其他镜像,比如经典的<code>hello-world</code>测试镜像。</p>
<p class="maodian"><a name="_lab2_0_4"></a></p><h3>5. 运行容器</h3>
<p>镜像只是静态的模板,要运行应用需要从镜像创建容器:</p>
<div class="jb51code"><pre class="brush:bash;">docker run hello-docker
</pre></div>
<p>日志输出:</p>
<div class="jb51code"><pre class="brush:bash;">PS E:\hello-world\hello-docker&gt; docker run hello-docker
你好,世界!
</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121209190564.png" /></p>
<p>执行后,终端立即输出了&quot;你好,世界!&quot;。这意味着:</p>
<ol><li>Docker从<code>hello-docker</code>镜像创建了一个新容器</li><li>容器内执行了<code>node /index.js</code>命令</li><li>Node.js解释器执行了我们的代码,输出结果到终端</li><li>程序执行完毕,容器自动停止</li></ol>
<p class="maodian"><a name="_lab2_0_5"></a></p><h3>6. 查看容器</h3>
<div class="jb51code"><pre class="brush:bash;">PS E:\hello-world\hello-docker&gt; docker ps   
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS    PORTS   NAMES
PS E:\hello-world\hello-docker&gt; </pre></div>
<div class="jb51code"><pre class="brush:bash;">PS E:\hello-world\hello-docker&gt; docker ps -a
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS                      PORTS   NAMES
9fadd3ad3798   hello-docker   "docker-entrypoint.s…"   54 seconds ago   Exited (0) 52 seconds ago             affectionate_burnell</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121209190552.png" /></p>
<p>运行<code>docker ps</code>查看当前正在运行的容器,发现没有结果。这是因为我们的应用执行完就退出了,容器也随之停止。</p>
<p>但使用<code>docker ps -a</code>查看所有容器(包括已停止的),可以看到刚刚运行的容器:</p>
<ul><li>状态为&quot;Exited (0)&quot;,表示正常退出</li><li>54秒前创建,52秒前退出</li><li>有一个随机生成的名字&quot;affectionate_burnell&quot;</li></ul>
<p>这就是容器与虚拟机的关键区别之一:容器是为了运行特定进程而存在的,当进程结束,容器的使命也就完成了。</p>
<p class="maodian"><a name="_lab2_0_6"></a></p><h3>7. 实践总结</h3>
<p>通过这个简单的实践,我们完成了Docker的核心工作流:</p>
<ol><li><strong>编写应用代码</strong> &rarr; 2. <strong>定义Dockerfile</strong> &rarr; 3. <strong>构建镜像</strong> &rarr; 4. <strong>运行容器</strong></li></ol>
<p>在这个过程中,我们学到了几个关键点:</p>
<ul><li><strong>镜像与容器的关系</strong>:镜像是静态的模板,容器是镜像的运行实例</li><li><strong>分层构建</strong>:Docker镜像采用分层结构,每一条指令都会创建一个新的层</li><li><strong>轻量级特性</strong>:容器随内部进程的结束而停止,资源占用更高效</li><li><strong>环境一致性</strong>:无论在哪里运行,容器内部环境都完全相同</li></ul>
<p>到此这篇关于Docker容器化Node.js应用教程的文章就介绍到这了,更多相关docker容器化node.js内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
頁: [1]
查看完整版本: Docker容器化Node.js应用操作教程