Bug: Using docker compose networking causes TypeError: t.mask is not a function or connection to hang when running .wait() or .query()
NexVeridian opened this issue ยท 2 comments
Describe the bug
When using next.js 14.1.0 within a docker container and docker surrealdb/surrealdb:latest-dev
using a docker url name
db.connect("ws://surrealdb:8000/rpc");
Docker compose file
# .env
DB_URL_PORT=surrealdb:8000
DB_USER=root
DB_PASSWORD=root
version: "3"
services:
nextjs:
build: .
env_file:
- .env
ports:
- 3000:3000
depends_on:
- surrealdb
networks:
- surrealdb-network
surrealdb:
container_name: surrealdb
image: surrealdb/surrealdb:latest-dev
env_file:
- .env
entrypoint:
- /surreal
- start
- --user
- $DB_USER
- --pass
- $DB_PASSWORD
- file:/data/surrealdb
restart: always
ports:
- 8000:8000
volumes:
- ./data:/data
networks:
- surrealdb-network
volumes:
data:
networks:
surrealdb-network:
causes the following error when running npm run build CMD ["node", "server.js"], from within the next.js docker
TypeError: t.mask is not a function
at e.exports.mask (/app/.next/server/chunks/235.js:1:59645)
at h.frame (/app/.next/server/chunks/235.js:1:78447)
at h.send (/app/.next/server/chunks/235.js:1:80497)
at L.send (/app/.next/server/chunks/235.js:2:9182)
at o.send (/app/.next/server/chunks/235.js:2:16756)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
docker file
# https://nextjs.org/docs/pages/building-your-application/deploying#docker-image
FROM node:20-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 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
# RUN yarn build
# If using npm comment out above and use below instead
RUN npm install
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
Or causes the connection to hang when using CMD ["npm ", "run", "dev"] from within the next.js docker file
docker file
# https://nextjs.org/docs/pages/building-your-application/deploying#docker-image
FROM node:20-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 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
# RUN yarn build
# If using npm comment out above and use below instead
RUN npm install
RUN npm run build
CMD ["npm ", "run", "dev"]
Other notes
- For both docker files there are no errors in the surrealdb docker container
- Running next.js not in docker, and connect to the surrealdb docker container with 0.0.0.0:8000, works correctly
- Using the rust sdk with a identical setup works correctly, with rust and surrealdb both in a docker container, connected with a docker compose network
let db = Surreal::new::<Ws>("surrealdb:8000".as_str()).await?;
Steps to reproduce
run this with the docker compose file from above
import { Surreal } from "surrealdb.js";
db.connect("ws://surrealdb:8000/rpc", {
namespace: "url",
database: "url",
auth: {
username: root,
password: root,
},
}
console.log(db);
let res = await db.query(`
select * from test
`);
For a runnable example see
https://github.com/NexVeridian/next-url-shortener
at this route http://localhost:3000/stats
and look at these two code file, which is also the same as the above code
https://github.com/NexVeridian/next-url-shortener/blob/main/src/components/db-utils.tsx
https://github.com/NexVeridian/next-url-shortener/blob/main/src/app/stats/db.tsx
Full logs with console.log(db) before the query
Attaching to nextjs-1, surrealdb
surrealdb |
surrealdb | .d8888b. 888 8888888b. 888888b.
surrealdb | d88P Y88b 888 888 'Y88b 888 '88b
surrealdb | Y88b. 888 888 888 888 .88P
surrealdb | 'Y888b. 888 888 888d888 888d888 .d88b. 8888b. 888 888 888 8888888K.
surrealdb | 'Y88b. 888 888 888P' 888P' d8P Y8b '88b 888 888 888 888 'Y88b
surrealdb | '888 888 888 888 888 88888888 .d888888 888 888 888 888
888
surrealdb | Y88b d88P Y88b 888 888 888 Y8b. 888 888 888 888 .d88P 888 d88P
surrealdb | 'Y8888P' 'Y88888 888 888 'Y8888 'Y888888 888 8888888P' 8888888P'
surrealdb |
surrealdb |
surrealdb | 2024-02-18T14:53:16.757212Z INFO surreal::env: Running 1.2.1 for linux on x86_64
surrealdb | 2024-02-18T14:53:16.757245Z WARN surreal::dbs: โ๐ IMPORTANT: Authenticatio
n is disabled. This is not recommended for production use. ๐โ
surrealdb | 2024-02-18T14:53:16.757258Z INFO surrealdb_core::kvs::ds: Starting kvs store at file:///data/surrealdb
surrealdb | 2024-02-18T14:53:17.308290Z INFO surrealdb_core::kvs::ds: Started kvs store at file:///data/surrealdb
surrealdb | 2024-02-18T14:53:17.310273Z WARN surrealdb_core::kvs::ds: Credentials were
provided, but existing root users were found. The root user 'root' will not be created
surrealdb | 2024-02-18T14:53:17.310287Z WARN surrealdb_core::kvs::ds: Consider removing the --user and --pass arguments from the server start command
surrealdb | 2024-02-18T14:53:17.310295Z INFO surrealdb::node: Started node agent
surrealdb | 2024-02-18T14:53:17.312579Z INFO surrealdb::net: Started web server on 0.0.0.0:8000
nextjs-1 | โฒ Next.js 14.1.0
nextjs-1 | - Local: http://a608860dff66:3000
nextjs-1 | - Network: http://172.21.0.3:3000
nextjs-1 |
nextjs-1 | โ Ready in 119ms
nextjs-1 | l {
nextjs-1 | socket: o {
nextjs-1 | url: 'ws://surrealdb:8000/rpc',
nextjs-1 | hooks: {
nextjs-1 | onConnect: [AsyncFunction: onConnect],
nextjs-1 | onClose: [Function: onClose],
nextjs-1 | onError: undefined
nextjs-1 | },
nextjs-1 | ws: L {
nextjs-1 | _events: [Object: null prototype],
nextjs-1 | _eventsCount: 4,
nextjs-1 | _maxListeners: undefined,
nextjs-1 | _binaryType: 'nodebuffer',
nextjs-1 | _closeCode: 1006,
nextjs-1 | _closeFrameReceived: false,
nextjs-1 | _closeFrameSent: false,
nextjs-1 | _closeMessage: <Buffer >,
nextjs-1 | _closeTimer: null,
nextjs-1 | _extensions: {},
nextjs-1 | _paused: false,
nextjs-1 | _protocol: '',
nextjs-1 | _readyState: 0,
nextjs-1 | _receiver: null,
nextjs-1 | _sender: null,
nextjs-1 | _socket: null,
nextjs-1 | _bufferedAmount: 0,
nextjs-1 | _isServer: false,
nextjs-1 | _redirects: 0,
nextjs-1 | _autoPong: true,
nextjs-1 | _url: 'ws://surrealdb:8000/rpc',
nextjs-1 | _req: [ClientRequest],
nextjs-1 | [Symbol(shapeMode)]: false,
nextjs-1 | [Symbol(kCapture)]: false
nextjs-1 | },
nextjs-1 | status: 1,
nextjs-1 | queue: {},
nextjs-1 | liveQueue: {},
nextjs-1 | unprocessedLiveResponses: {},
nextjs-1 | ready: Promise {
nextjs-1 | <pending>,
nextjs-1 | [Symbol(async_id_symbol)]: 157,
nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142,
nextjs-1 | [Symbol(kResourceStore)]: [Object],
nextjs-1 | [Symbol(kResourceStore)]: [Object],
nextjs-1 | [Symbol(kResourceStore)]: [Object]
nextjs-1 | },
nextjs-1 | closed: Promise {
nextjs-1 | <pending>,
nextjs-1 | [Symbol(async_id_symbol)]: 151,
nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142,
nextjs-1 | [Symbol(kResourceStore)]: [Object],
nextjs-1 | [Symbol(kResourceStore)]: [Object],
nextjs-1 | [Symbol(kResourceStore)]: [Object]
nextjs-1 | },
nextjs-1 | resolveClosed: [Function (anonymous)],
nextjs-1 | socketClosureReason: { '1000': 'CLOSE_NORMAL' }
nextjs-1 | },
nextjs-1 | pinger: n { pinger: undefined, interval: 30000 },
nextjs-1 | connection: {
nextjs-1 | auth: { username: 'root', password: 'root' },
nextjs-1 | namespace: 'url',
nextjs-1 | database: 'url'
nextjs-1 | },
nextjs-1 | ready: Promise {
nextjs-1 | <pending>,
nextjs-1 | [Symbol(async_id_symbol)]: 149,
nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142,
nextjs-1 | [Symbol(kResourceStore)]: {
nextjs-1 | headers: [Getter],
nextjs-1 | cookies: [Getter],
nextjs-1 | mutableCookies: [Getter],
nextjs-1 | draftMode: [Getter]
nextjs-1 | },
nextjs-1 | [Symbol(kResourceStore)]: {
nextjs-1 | isStaticGeneration: false,
nextjs-1 | urlPathname: '/stats',
nextjs-1 | pagePath: '/stats/page',
nextjs-1 | incrementalCache: [IncrementalCache],
nextjs-1 | isRevalidate: true,
nextjs-1 | isPrerendering: undefined,
nextjs-1 | fetchCache: 'default-no-store',
nextjs-1 | isOnDemandRevalidate: false,
nextjs-1 | isDraftMode: false,
nextjs-1 | postpone: undefined,
nextjs-1 | fetchMetrics: []
nextjs-1 | },
nextjs-1 | [Symbol(kResourceStore)]: { isAction: true }
nextjs-1 | },
nextjs-1 | resolveReady: [Function (anonymous)],
nextjs-1 | rejectReady: [Function (anonymous)],
nextjs-1 | strategy: 'ws',
nextjs-1 | hooks: {}
nextjs-1 | }
nextjs-1 | TypeError: t.mask is not a function
nextjs-1 | at e.exports.mask (/app/.next/server/chunks/235.js:1:59645)
nextjs-1 | at h.frame (/app/.next/server/chunks/235.js:1:78447)
nextjs-1 | at h.send (/app/.next/server/chunks/235.js:1:80497)
nextjs-1 | at L.send (/app/.next/server/chunks/235.js:2:9182)
nextjs-1 | at o.send (/app/.next/server/chunks/235.js:2:16756)
nextjs-1 | at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
db.query causes the TypeError: t.mask is not a function, db.create is ok
Expected behaviour
The query should run
SurrealDB version
1.2.1, docker surrealdb/surrealdb:latest-dev
SurrealDB.js version
0.11.0
Contact Details
Is there an existing issue for this?
- I have searched the existing issues
Code of Conduct
- I agree to follow this project's Code of Conduct
Hey @NexVeridian, it is quite possible that the docker image used for building nextjs ships an old version of NodeJS out of the box, which probably lacks certain functionality, and which is likely different from the version of NodeJS installed on your system. I've never really tested it, but my guess would be that anything above NodeJS v16 will work, but while you're at it you might aswell set it to node 18 or 20 ๐
I think I have an update to date version
FROM node:20-alpine AS base
I just swapped it to FROM node:20-bookworm AS base
both have the same TypeError: t.mask is not a function as above
here is the full docker file, same as the one from the next.js docs
# https://nextjs.org/docs/pages/building-your-application/deploying#docker-image
FROM node:20-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 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
# RUN yarn build
# If using npm comment out above and use below instead
RUN npm install
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]