My Little World

docker

一种容器技术,解决跨环境迁移问题

核心概念

  1. 镜像: 容器的模板 (模具)
  2. 容器: 镜像的实例 (糕点)
  3. 镜像仓库: 存储镜像的中心仓库 (模具库)

客户端下载
镜像库

相关命令行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
docker --version # 查看docker 版本 安装成功

docker pull nginx # 下载nginx 镜像

docker images # 查看已安装所有镜像
# 输出结果如下:
# IMAGE ID DISK USAGE CONTENT SIZE EXTRA
# nginx:latest d0d674272be3 271MB 67.9MB

docker rmi d0d674272be3 # 删除nginx 镜像 (rmi + 镜像ID)
docker rmi nginx # 删除nginx 镜像 (rmi + 镜像名)

docker run nginx # 启动nginx 容器,但是不会在后台运行

docker run -d -p 80:80 nginx # 启动nginx 容器
-d 表示后台运行
-p 80:80 表示映射端口,冒号后面80 是容器运行端口,冒号前面80 是主机端口

docker ps # 查看所有正在运行的容器
# 输出结果如下:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 465f1343d282 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp kind_lovelace



docker stop 465f1343d282 # 停止nginx 容器
docker ps -a # 查看所有容器,包括停止的容器
docker start 465f1343d282 # 启动nginx 容器
docker rm -f 465f1343d282 # 删除nginx 容器
-f 表示强制删除, 即使容器正在运行也会删除


docker run -d -p 80:80 -v /Users/project/docker/html:/usr/share/nginx/html nginx # 启动nginx 容器,挂载本地目录到容器目录
-v 表示挂载宿主机目录到容器目录,冒号后面是容器目录,冒号前面是宿主机目录,此时访问宿主机IP:80 就可以访问到宿主机目录下的文件了 【绑定挂载】
宿主机目录会覆盖容器内目录,宿主机目录修改改变时,容器内目录也会改变,容器被删除时,目录内容在宿主机上依然存在,从而实现数据持久化

docker volume create docker_html # 创建一个docker_html 的卷,卷名称为docker_html
docker run -d -p 80:80 -v docker_html:/usr/share/nginx/html nginx # 启动nginx 容器,挂载docker_html 卷到容器目录, 就不用指定宿主机挂载目录了
docker volume inspect docker_html # 查看docker_html 卷信息
docker volume rm docker_html # 删除docker_html 卷
docker volume prune -a # 删除所有容器都未使用的卷

# 启动mongoDB 容器,并传入环境变量,设置数据库用户名和密码
docker run -d \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=tech \
-e MONGO_INITDB_ROOT_PASSWORD=tech123456 \

-e 表示设置环境变量

docker run -d --name my_nginx nginx # 启动nginx 容器,容器名称为my_nginx
--name 表示设置容器名称,要再宿主机中唯一,方便识别,之后删除容器也可用这里命名的这个名字

docker run -it --rm alpine # 临时进入容器调试
-it 表示进入容器并开启交互模式
--rm 表示容器退出后,自动删除容器

docker run -d --restart always nginx # 启动nginx 容器,容器退出后,自动重启
--restart 配置容器停止时的重启策略
always 表示容器退出(崩溃,断电等意外 + 手动停止)后,自动重启
unless-stopped 跟always 类似,但是容器被手动停止时,不会重启

docker inspect 465f1343d282 # 查看nginx 容器信息, 包括启动时的配置参数

docker create nginx # 创建一个nginx 容器,但是不会在后台运行 需要再执行docker start nginx 启动容器
docker logs 465f1343d282 # 查看nginx 容器日志
docker logs 465f1343d282 -f # 滚动查看日志
-f --follow 表示实时查看日志,容器退出后,日志也会继续打印

docker exec 465f1343d282 linux命令 # 进入容器 执行linux命令
docker exec -it 465f1343d282 /bin/sh # 进入一个正在运行的docker 容器 内部,获得一个交互式的命令行环境,容器内容就像一个独立操作系统
cat /etc/os-release # 查看当前容器内Linux 发行版本,方便安装其他命令行,eg.vi
exit # 退出容器交互式环境,容器会自动停止

dockerfile


dockerfile 是一个文件,用于描述如何构建一个镜像
制作镜像步骤

  1. 实际脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    docker_test/main.py
    # 启动一个fastapi服务,默认端口为8000
    import uvicorn
    from fastapi import FastAPI

    app = FastAPI()


    @app.get("/")
    def read_root():
    return {"Hello": "World"}

    if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

    docker_test/requirements.txt
    fastapi
    uvicorn
  2. 创建Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    docker_test/Dockerfile
    # 注意Dockerfile 是一个文本文件,所有命令都大写,不带任何后缀

    # 指定基础镜像为python:3.13-slim
    FROM python:3.13-slim

    WORKDIR /app

    COPY . .

    RUN pip install -r requirements.txt

    EXPOSE 8000

    CMD ["python3", "main.py"]
  3. 构建镜像

    1
    2
    3
    4
    5
    6
    7
    docker build -t docker_test . # 在docker_test 目录下,构建镜像,镜像名称为docker_test

    docker run -d -p 8000:8000 docker_test # 启动容器,映射端口8000:8000,容器名称为docker_test,本地测试

    docker login # 登录docker 镜像仓库,需要输入用户名和密码,登录后即可推送镜像到仓库
    docker build -t yoohannah/docker_test . # 在docker_test 目录下,重新构建携带用户名的镜像,镜像名称为yoohannah/docker_test,这里用户名充当namespace作用
    docker push yoohannah/docker_test # 推送镜像到仓库
  4. 查找使用
    在https://hub.docker.com/ 查找yoohannah/docker_test

    1
    docker pull yoohannah/docker_test

其他人即可以使用刚刚创建的镜像

自建镜像Repositories

docker 网络

默认bridge ,桥接模式

容器内部有容器网络,容器可以根据分配的IP 地址进行通信
容器网络和宿主机网路隔离

1
docker network create network1 # 创建一个子网network1, 属于bridge 模式一种

可以指定容器加入不同子网,
在不同子网的容器之间不能直接通信,
在相同子网的容器之间可以相互通信,docker 子网内部有一个dns机制,可以把名字转成IP地址
因此,同一个子网的容器,可以直接使用容器名字互相访问,而不必使用IP地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker run -d --name docker_test --network network1 docker_test
docker run -d --name my_nginx --network network1 nginx

docker exec -it my_nginx /bin/sh
apt-get install -y iputils-ping
ping docker_test # 测试容器间通信,在my_nginx 容器内ping docker_test 容器

打印结果:
PING docker_test (172.18.0.2) 56(84) bytes of data.
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=1 ttl=64 time=0.254 ms
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=2 ttl=64 time=0.166 ms
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=3 ttl=64 time=0.195 ms
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=4 ttl=64 time=0.169 ms
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=5 ttl=64 time=0.206 ms
64 bytes from docker_test.network1 (172.18.0.2): icmp_seq=6 ttl=64 time=0.200 ms
^C
--- docker_test ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5128ms
rtt min/avg/max/mdev = 0.166/0.198/0.254/0.029 ms

host 模式

docker 容器直接共享宿主机的网络
容器直接使用宿主机的IP地址,无-p 映射端口,容器服务直接运行在宿主机的端口上
通过宿主机的IP地址和端口,可以直接访问到容器的服务
mac 需要开启设置
开启路径是:Settings → Resources → Network → Enable host networking。

1
2
3
4
5
6
7
docker run -d --network host nginx

# 进入容器内部 产看ip 信息
docker exec -it ae2a9a90a075 /bin/sh
apt-get update
apt-get install iproute2 -y
ip addr show# 查看容器内ip 信息

直接用宿主机的IP地址和端口,可以直接访问到容器的服务

1
http://127.0.0.1:80

none 模式

容器不联网

查看docker 网络

1
2
3
4
5
6
7
8
9
docker network list # 展示所有docker网络

NETWORK ID NAME DRIVER SCOPE
82a512410da4 bridge bridge local
97f3e9474823 host host local
383595c36af6 network1 bridge local
415059793d19 none null local

docker network rm NETWORKID # 删除指定网络

docker compose

容器编排技术
使用yml文件管理多个容器,里面列出了容器之间是如何创建以及如何协同工作的
docker compose 文件可以被理解成一个多个docker run 命令 按照特定格式列到了一个文件中

docker 为每一个 compose 文件会自动创建子网,同一个 compose 文件中定义的所有容器自动加入同一个子网,所以在文件中不用二外写入网络创建和指定子网

compose 文件 可以自定义容器启动顺序

1
2
3
4
5
6
7
# 当前目录下有docker-compose.yaml 文件
docker compose up -d # 创建子网 启动compose 文件中定义的所有容器,-d 表示后台运行
docker compose down # 停止并删除compose 文件中定义的所有容器
docker compose stop # 停止compose 文件中定义的所有容器
docker compose start # 启动compose 文件中定义的所有容器

docker compose -f /user/test.yaml up -d # 通过-f 指定非标 yaml 文件,启动容器

动手操作 部署nextjs 项目到docker 容器

官方文档:https://docs.docker.com/guides/nextjs

1
2
3
4
5
// 创建项目
npm create next-app@latest my-app --yes

// 启动项目 后 对项目进行一些系列开发改造
npm run dev

下面进入主要部署阶段将项目打包,打包产物放到docker 里面的ngnix 容器中,然后通过端口转发进行访问
即打包静态产物上传服务器后,修改ngnix配置指向这个目录,即可访问到项目

准备工作

使用合适node 版本,防止镜像生成失败

1
2
3
4
5
# 看下当前本地node 版本
node -v

# 去docker 官网拉对应node 镜像 https://hub.docker.com/_/node/tags?name=22.21.1
docker pull node:22.21.1-slim

方式一: Next.js with standalone output

这种方式将nextjs项目打包成node服务,适合全栈场景

Standalone output (output: “standalone”) makes Next.js build a self-contained output that includes only the files and dependencies needed to run the application. A single node server.js can serve the app, which is ideal for Docker and supports server-side rendering, API routes, and incremental static regeneration. For details, see the Next.js output configuration documentation (including the “standalone” option).

The container runs the Next.js server with Node.js on port 3000.

next.config.ts

1
2
3
4
5
6
7
8
9
// next.config.ts

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
output: "standalone",
};

export default nextConfig;

复制官网dockerfile 修改node 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

# ============================================
# Stage 1: Dependencies Installation Stage
# ============================================
# 指定合适node 版本
ARG NODE_VERSION=22.21.1-slim

FROM node:${NODE_VERSION} AS dependencies

# Set working directory
WORKDIR /app

# Copy package-related files first to leverage Docker's caching mechanism
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./

# Install project dependencies with frozen lockfile for reproducible builds
RUN --mount=type=cache,target=/root/.npm \
--mount=type=cache,target=/usr/local/share/.cache/yarn \
--mount=type=cache,target=/root/.local/share/pnpm/store \
if [ -f package-lock.json ]; then \
npm ci --no-audit --no-fund; \
elif [ -f yarn.lock ]; then \
corepack enable yarn && yarn install --frozen-lockfile --production=false; \
elif [ -f pnpm-lock.yaml ]; then \
corepack enable pnpm && pnpm install --frozen-lockfile; \
else \
echo "No lockfile found." && exit 1; \
fi

# ============================================
# Stage 2: Build Next.js application in standalone mode
# ============================================

FROM node:${NODE_VERSION} AS builder

# Set working directory
WORKDIR /app

# Copy project dependencies from dependencies stage
COPY --from=dependencies /app/node_modules ./node_modules

# Copy application source code
COPY . .

ENV NODE_ENV=production

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED=1

# Build Next.js application
# If you want to speed up Docker rebuilds, you can cache the build artifacts
# by adding: --mount=type=cache,target=/app/.next/cache
# This caches the .next/cache directory across builds, but it also prevents
# .next/cache/fetch-cache from being included in the final image, meaning
# cached fetch responses from the build won't be available at runtime.
RUN if [ -f package-lock.json ]; then \
npm run build; \
elif [ -f yarn.lock ]; then \
corepack enable yarn && yarn build; \
elif [ -f pnpm-lock.yaml ]; then \
corepack enable pnpm && pnpm build; \
else \
echo "No lockfile found." && exit 1; \
fi

# ============================================
# Stage 3: Run Next.js application
# ============================================

FROM node:${NODE_VERSION} AS runner

# Set working directory
WORKDIR /app

# Set production environment variables
ENV NODE_ENV=production
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the run time.
# ENV NEXT_TELEMETRY_DISABLED=1

# Copy production assets
COPY --from=builder --chown=node:node /app/public ./public

# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown node:node .next

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=node:node /app/.next/standalone ./
COPY --from=builder --chown=node:node /app/.next/static ./.next/static

# If you want to persist the fetch cache generated during the build so that
# cached responses are available immediately on startup, uncomment this line:
# COPY --from=builder --chown=node:node /app/.next/cache ./.next/cache

# Switch to non-root user for security best practices
USER node

# Expose port 3000 to allow HTTP traffic
EXPOSE 3000

# Start Next.js standalone server
CMD ["node", "server.js"]

构建镜像

本地构建运行镜像后,上传到docker 仓库 ,下载测试

1
2
3
4
5
6
7
docker build -t nextjs-standalone .
docker run -d -p 8000:3000 nextjs-standalone

docker build -t yoohannah/nextjs-standalone .
docker push yoohannah/nextjs-standalone
docker pull yoohannah/nextjs-standalone
docker run -d -p 8002:3000 yoohannah/nextjs-standalone

方式二: Next.js with export output

这种方式将nextjs项目打包成静态文件, 适合静态网站部署

准备工作

依赖 nginxinc/nginx-unprivileged 镜像

1
docker pull nginxinc/nginx-unprivileged:alpine3.22

修改next.config.ts

指定打包方式为export

1
2
3
4
5
6
7
8
9
10
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
trailingSlash: true,
images: {
unoptimized: true,
},
};

export default nextConfig;

复制官网dockerfile 修改node 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# ============================================
# Stage 1: Dependencies Installation Stage
# ============================================

ARG NODE_VERSION=22.21.1-slim
ARG NGINXINC_IMAGE_TAG=alpine3.22

FROM node:${NODE_VERSION} AS dependencies

# Set the working directory
WORKDIR /app

# Copy package-related files first to leverage Docker's caching mechanism
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./

# Install project dependencies with frozen lockfile for reproducible builds
RUN --mount=type=cache,target=/root/.npm \
--mount=type=cache,target=/usr/local/share/.cache/yarn \
--mount=type=cache,target=/root/.local/share/pnpm/store \
if [ -f package-lock.json ]; then \
npm ci --no-audit --no-fund; \
elif [ -f yarn.lock ]; then \
corepack enable yarn && yarn install --frozen-lockfile --production=false; \
elif [ -f pnpm-lock.yaml ]; then \
corepack enable pnpm && pnpm install --frozen-lockfile; \
else \
echo "No lockfile found." && exit 1; \
fi

# ============================================
# Stage 2: Build Next.js Application
# ============================================

FROM node:${NODE_VERSION} AS builder

# Set the working directory
WORKDIR /app

# Copy project dependencies from dependencies stage
COPY --from=dependencies /app/node_modules ./node_modules

# Copy application source code
COPY . .

ENV NODE_ENV=production

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED=1

# Build Next.js application
RUN --mount=type=cache,target=/app/.next/cache \
if [ -f package-lock.json ]; then \
npm run build; \
elif [ -f yarn.lock ]; then \
corepack enable yarn && yarn build; \
elif [ -f pnpm-lock.yaml ]; then \
corepack enable pnpm && pnpm build; \
else \
echo "No lockfile found." && exit 1; \
fi

# =========================================
# Stage 3: Serve Static Files with Nginx
# =========================================

FROM nginxinc/nginx-unprivileged:${NGINXINC_IMAGE_TAG} AS runner

# Set the working directory
WORKDIR /app

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the run time.
# ENV NEXT_TELEMETRY_DISABLED=1

# Copy custom Nginx config
COPY nginx.conf /etc/nginx/nginx.conf

# Copy the static build output from the build stage to Nginx's default HTML serving directory
COPY --from=builder /app/out /usr/share/nginx/html

# Non-root user for security best practices
USER nginx

# Expose port 8080 to allow HTTP traffic
EXPOSE 8080

# Start Nginx directly with custom config
ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"]
CMD ["-g", "daemon off;"]

创建nginx.conf 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Minimal Nginx config for static Next.js app
worker_processes 1;

# Store PID in /tmp (always writable)
pid /tmp/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

# Disable logging to avoid permission issues
access_log off;
error_log /dev/stderr;

# Optimize static file serving
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;

# 从宿主机访问时,需要关闭绝对重定向和端口在定向,否则会导致404错误,
# 比如宿主机用8000 访问 nginx 8080 端口,
# 页面url 会变成 http://localhost:8000/about 变成 http://localhost:8080/about/ ,导致404错误
# 不加下面配置的话,宿主机只能用8080端口访问
absolute_redirect off;
port_in_redirect off;

# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;

server {
listen 8080;
server_name localhost;

# Serve static files
root /usr/share/nginx/html;
index index.html;

# Handle Next.js static export routing
# See: https://nextjs.org/docs/app/guides/static-exports#deploying
location / {
try_files $uri $uri.html $uri/ =404;
}

# This is necessary when `trailingSlash: false` (default).
# You can omit this when `trailingSlash: true` in next.config.
# Handles nested routes like /blog/post -> /blog/post.html
# https://nextjs.org/docs/app/api-reference/config/next-config-js/trailingSlash
# 如果是静态路由,打包结果是 /blog/post/index.html,需要注释掉这里的配置
# location ~ ^/(.+)/$ {
# rewrite ^/(.+)/$ /$1.html break;
# }

# Serve Next.js static assets
location ~ ^/_next/ {
try_files $uri =404;
expires 1y;
add_header Cache-Control "public, immutable";
}

# Optional 404 handling
error_page 404 /404.html;
location = /404.html {
internal;
}
}
}

创建compose.yaml 文件

1
2
3
4
5
6
services:
server:
build:
context: .
ports:
- 8080:8080

创建.dockerignore file

The .dockerignore file tells Docker which files and folders to exclude when building the image.

注意跟打包不同,打包的时候,output = export 的时候会将所有静态文件打包到out 目录下,
如果项目中有api 文件也会进行打包,所以当前项目将api 目录通过添加下划线前缀‘_’ 来排除, 避免打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Dependencies (installed inside the image, never copy from host)
node_modules/
.pnp/
.pnp.js
.pnpm-store/

# Next.js build output (generated during the image build)
.next/
out/
dist/
build/
.vercel/

# Testing (not needed in the production image)
coverage/
.nyc_output/
__tests__/
__mocks__/
jest/
cypress/
playwright-report/
test-results/
.vitest/

# Environment files (avoid leaking secrets into the build context)
.env
.env*
.env.local
.env.development.local
.env.test.local
.env.production.local

# Debug and log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
*.log

# IDE and editor files
.vscode/
.idea/
.cursor/
.cursorrules
.copilot/
*.swp
*.swo
*~

# Git
.git/
.gitignore
.gitattributes

# Docker files (reduce build context; not needed inside the image)
Dockerfile*
.dockerignore
docker-compose*.yml
compose*.yaml

# Documentation (not needed in the image)
*.md
docs/

# CI/CD (not needed in the image)
.github/
.gitlab-ci.yml
.travis.yml
.circleci/
Jenkinsfile

# TypeScript and build metadata
*.tsbuildinfo

# Cache and temporary directories
.cache/
.parcel-cache/
.eslintcache
.stylelintcache
.turbo/
.tmp/
.temp/

# Sensitive or dev-only config (optional; omit if your build needs these)
.pem
.editorconfig
.prettierrc*
.eslintrc*
.stylelintrc*
.babelrc*
*.iml

# OS-specific files
.DS_Store
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
Desktop.ini

生成镜像并运行

1
2
3
4
5
6
7
docker build -t nextjs_export .
docker run -d -p 8003:8080 nextjs_export

docker build -t yoohannah/nextjs-export .
docker push yoohannah/nextjs-export
docker pull yoohannah/nextjs-export
docker run -d -p 8080:8080 yoohannah/nextjs-export

小结

  1. 创建项目,npm run dev, npm run build 没问题后再开始构建镜像
  2. 先构建本地镜像,运行测试没问题后,再构建上传到hub 的镜像
  3. docker pull 获取远端镜像,后运行测试,确认正常

my-app-nextjs 项目代码

容器内网络测试

1
2
3
4
5
6
7
8
9
10
11
docker run -d -p 8000:3000 yoohannah/nextjs-standalone
docker exec -it ea04228558df /bin/sh
node -e "
fetch('https://www.baidu.com')
.then(r => console.log('HTTP', r.status))
.catch(e => console.error('FAIL', e.message));
"

docker run -d -p 8010:8080 nextjs_export
docker exec -it 646967e74f44 /bin/sh
curl -I https://www.baidu.com