我会通过用Docker部署一个Node.js编写的web应用程序,来深入地理解Docker容器的本质。
一、准备工作
在开始前,需要在你的Mac电脑中安装Docker。在官方网站上有各种环境下的安装指南,用Mac电脑的就看Install Docker Desktop on Mac。
安装Docker
安装步骤非常简单:
- 如果是M1芯片的arm64架构,就下载Docker for Mac with Apple silicon。
- 双击Docker.dmg文件,然后把鲸鱼图标拖放到Applications文件夹即可。
运行Docker
在应用中找到Docker图标,点击运行。
运行后,在菜单栏会看到多了一个鲸鱼图标:
然后,在终端用命令查下Docker的版本:
docker --version
再查下docker info是不是也正常。如果都正常,就可以用Node.js编写web应用了。
在这里,我是用Nestjs写的应用程序,代码非常简单。也就是用Nestjs的cli工具生成的,创建应用的这一步就直接跳过了,直接上代码:- // app.controller.ts部分
- import { Controller, Get } from '@nestjs/common';
- import { AppService } from './app.service';
- @Controller()
- export class AppController {
- constructor(private readonly appService: AppService) {}
- @Get()
- getHello(): string {
- return this.appService.getHello();
- }
- }
- // app.module.ts部分
- import { Module } from '@nestjs/common';
- import { AppController } from './app.controller';
- import { AppService } from './app.service';
- @Module({
- imports: [],
- controllers: [AppController],
- providers: [AppService],
- })
- export class AppModule {}
- // app.service.ts部分
- import { Injectable } from '@nestjs/common';
- @Injectable()
- export class AppService {
- getHello(): string {
- return 'Hello World!';
- }
- }
- // main.ts部分
- import { NestFactory } from '@nestjs/core';
- import { AppModule } from './app.module';
- async function bootstrap() {
- const app = await NestFactory.create(AppModule);
- await app.listen(process.env.PORT ?? 3000);
- }
- bootstrap();
复制代码 在上面的代码中,就是用Nest框架启动了一个Web服务器,只有一个简单的功能是:打印出“Hello World!”。
那么,将这样的一个应用程序容器化,第一步是制作容器镜像。
二、Docker的配置文件:Dockerfile
首先,我们在这个Nestjs的应用程序的根目录下创建一个文本文件,文件名是:Dockerfile,没有扩展名的。- # 使用官方提供的Node.js开发镜像作为基础镜像
- FROM node:22-slim
- # 工作目录切换为 /usr/src/app
- WORKDIR /usr/src/app
- # 将 package.json复制到当前目录下
- COPY package.json ./
- RUN npm config set registry https://registry.npmmirror.com/
- # 使用npm命令安装这个应用所需要的依赖
- RUN npm install
- RUN npm install -g pnpm
- COPY . .
- # 暴露给外界访问容器3000端口
- EXPOSE 3000
- # 设置容器进程为:pnpm run start:dev,即:这个Node应用开发环境的启动命令
- CMD ["pnpm", "run", "start:dev"]
复制代码 通过Dockerfile的内容,可以看到是用一些标准的大写词语来描述Docker镜像。这些大写的词语就是按上面内容顺序来处理的。
三、制作Docker镜像
接下来,可以用Docker制作这个应用的镜像了,在当前目录执行:
docker build -t nestjs-app .
这个-t是给这个镜像加tag,也就是起个名儿。docker build会自动加载当前目录中的Dockerfile,然后按照里面的顺序一个个的执行其中的大写词语。在这个过程里面,实际上就等同于Docker使用基础镜像启动了一个容器,然后在这个容器中一个个执行Dockerfile中的大写词语。
在每次执行后,都会生成一个对应的镜像层。
Docker build操作完成后,可以用 docker image命令查下结果:- docker image ls
- REPOSITORY TAG IMAGE ID CREATED SIZE
- nestjs-app latest 2badda7aef21 2 hours ago 1.11GB
复制代码 四、使用Docker镜像启动容器
使用这个镜像,用docker run命令来启动容器:
docker run nestjs-app
在镜像名的后面,什么都不用写,这是因为在Dockerfile中已经指定CMD了,不然,就得把进程的开发环境启动命令加在后面:
docker run -p 3000:8080 nestjs-app pnpm run start:dev
在容器启动了之后,可以用docker ps命令看一下:- docker ps
- CONTAINER ID IMAGE COMMAND CREATED
- 8015b4eac7eb nestjs-app "docker-entrypoint.s…" 23 seconds ago
复制代码 在这个命令中,我通过-p 3000:8080告诉Docker,把容器中8080端口映射到宿主机的3000端口。
这样,访问宿主机的3000端口,就可以看到容器中应用程序返回的结果:
这是VSCode中的插件 Thunder client,类似用curl http://localhost:3000。
这样,已经使用容器完成了一个web应用的开发与测试。
五、总结
这里我用了一个Node.js应用作为实例,讲解了Docker容器使用的主要场景。熟悉了这些操作,也就基本摸清了Docer容器核心功能。
在容器进程“pnpm run start:dev”,是进行在由Linux Namespace和Cgroups构成的隔离环境中;运行它所需要的各种文件,由挂载在rootfs层了。
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |