I face this exact error but Idk how to solve it. Idk if my Windows firewall is blocking it & if it is, then how would I solve it? for context, I’m not using docker desktop. just docker with wsl2 on Windows 11.
I’m dockerizing a remix app in node.js.
docker-compose.yml
version: "3.8"
services:
redis:
image: redis:7.2.4-alpine
container_name: aff_redis_dev
env_file:
- ../../.env.development
restart: always
ports:
- 6379:6379
command: redis-server --save 60 1 --loglevel warning --requirepass 123456abc
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 30s
retries: 50
volumes:
- redis_data:/data
web:
image: affiliates:0.0.1
build:
context: ../../
dockerfile: docker/development/Dockerfile
container_name: aff_dev
env_file:
- ../../.env.development
environment:
- WATCHPACK_POLLING=true
- CHOKIDAR_USEPOLLING=true
ports:
- 3001:3000
- 8002:8002
volumes:
- ./:/app
- ../../data:/data
restart: unless-stopped
depends_on:
redis:
condition: service_healthy
volumes:
redis_data:
driver: local
Dockerfile
FROM node:20-alpine AS base
# mostly inspired from https://github.com/BretFisher/node-docker-good-defaults/blob/main/Dockerfile & https://github.com/remix-run/example-trellix/blob/main/Dockerfile
# 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
RUN corepack enable && corepack prepare [email protected] --activate
# set the store dir to a folder that is not in the project
RUN pnpm config set store-dir ~/.pnpm-store
RUN pnpm fetch
# 1. Install all dependencies including dev dependencies
FROM base AS deps
# Root user is implicit so you don't have to actually specify it. From https://stackoverflow.com/a/45553149/6141587
# USER root
USER node
# WORKDIR now sets correct permissions if you set USER first so `USER node` has permissions on `/app` directory
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY --chown=node:node package.json pnpm-lock.yaml* ./
COPY --chown=node:node /app/drizzle/migrations ./migrations
RUN pnpm install --frozen-lockfile --prefer-offline
# 2. Start the development server
# Inspired by https://github.com/vercel/next.js/discussions/36935
RUN mkdir -p /app/.cache && chown -R node:node /app/.cache
# Persist the remix cache in a volume
VOLUME ["/app/.cache"]
# COPY --from=deps --chown=node:node /app/node_modules ./node_modules
COPY --chown=node:node . .
# This will do the trick, use the corresponding env file for each environment.
COPY --chown=node:node .env.development .env.development
# Copied from https://stackoverflow.com/a/69867550/6141587
USER root
# Give /data directory correct permissions otherwise WAL mode won't work. It means you can't have 2 users writing to the database at the same time without this line as *.sqlite-wal & *.sqlite-shm are automatically created & deleted when *.sqlite is busy.
RUN mkdir -p /data && chown -R node:node /data
USER node
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME 0.0.0.0
ENV NODE_ENV development
COPY --chown=node:node public ./public
# Move the drizzle directory to the runtime image
COPY --chown=node:node /app/drizzle/migrations ./migrations
COPY --chown=node:node scripts/drizzle-migrate.mjs ./scripts/drizzle-migrate.mjs
COPY --chown=node:node scripts/package.json ./scripts/package.json
COPY --chown=node:node scripts/pnpm-lock.yaml ./scripts/pnpm-lock.yaml
COPY --chown=node:node scripts/run.dev.sh ./run.dev.sh
RUN chmod +x run.dev.sh
CMD ["sh", "run.dev.sh"]
run.dev.sh
#!/bin/bash
set -e
# Set the directory of the database in a variable
DB_PATH=/data/affiliates.dev.sqlite
# Set to true only when you want to run the migrate script, i.e when changing database schema
# Automate it by only setting it to true by tracking `entries.idx` in `migrations/meta/_journal.json`
MIGRATE_DATABASE=false
# Inspired by https://pranavmalvawala.com/run-script-only-on-first-start-up & https://serverfault.com/a/1134812/1078165
FIRST_TIME_MIGRATION_DEV="FIRST_TIME_MIGRATION_DEV"
if [[ ! -e /data/$FIRST_TIME_MIGRATION_DEV ]] || [[ $MIGRATE_DATABASE = true ]]; then
# Place your script that you only want to run on the first startup.
echo 'Initialize database first time only'
touch /data/$FIRST_TIME_MIGRATION_DEV
echo "Migrating database '/data/affiliates.dev.sqlite'"
pnpm db:migrate:dev & PID=$!
# Wait for migration to finish
wait $PID
fi
echo "Starting development server..."
pnpm dev
if I remove the volumes mapping - ./:/app
from docker-compose.yml
, then everything works fine.
but if i add it, i get this error:
sh: can’t open ‘run.dev.sh’: No such file or directory
as said in the other answer, i tried this command:
docker run -it --rm -v "$(pwd):/app" busybox ls -l /app
i got this:
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
7b2699543f22: Pull complete
Digest: sha256:650fd573e056b679a5110a70aabeb01e26b76e545ec4b9c70a9523f2dfaf18c6
Status: Downloaded newer image for busybox:latest
total 293
-rwxrwxrwx 1 1000 1000 1432 Mar 10 10:53 Makefile
-rwxrwxrwx 1 1000 1000 13 Jan 21 06:43 README.md
drwxrwxrwx 1 1000 1000 512 Jan 24 05:42 app
drwxrwxrwx 1 1000 1000 512 Jan 25 16:23 build
drwxrwxrwx 1 1000 1000 512 Mar 10 09:30 data
drwxrwxrwx 1 1000 1000 512 Mar 9 13:11 docker
-rwxrwxrwx 1 1000 1000 265 Jan 25 06:22 drizzle.config.ts
-rwxrwxrwx 1 1000 1000 80 Mar 10 14:17 env.d.ts
-rwxrwxrwx 1 1000 1000 324 Feb 28 07:21 litestream.yml
drwxrwxrwx 1 1000 1000 512 Mar 11 07:27 node_modules
-rwxrwxrwx 1 1000 1000 2574 Mar 11 07:27 package.json
-rwxrwxrwx 1 1000 1000 289002 Mar 11 07:27 pnpm-lock.yaml
-rwxrwxrwx 1 1000 1000 80 Mar 11 07:26 postcss.config.mjs
-rwxrwxrwx 1 1000 1000 247 Mar 10 10:36 prettier.config.cjs
drwxrwxrwx 1 1000 1000 512 Jan 25 16:23 public
-rwxrwxrwx 1 1000 1000 156 Mar 10 11:56 remix.config.cjs
drwxrwxrwx 1 1000 1000 512 Mar 10 12:10 scripts
-rwxrwxrwx 1 1000 1000 171 Jan 19 09:18 tailwind.config.ts
-rwxrwxrwx 1 1000 1000 585 Mar 10 14:18 tsconfig.json
-rwxrwxrwx 1 1000 1000 450 Mar 11 07:20 vite.config.ts
i understood that the error meant that it didn’t find run.dev.sh
in the top-most directory on my host side but i don’t know how to solve the error?
i tried $pwd
, $(pwd)
, $(PWD)
, ${PWD}
& many other variations. finally, settled on ./:/app
as it is the provided solution here that works cross-platform.
how do I solve this?
the reason I’m mapping the current directory is that I want hmr/live-reloading to work with remix.
but I have to use docker as I need Redis which isn’t directly available in Windows. of course, I can just start a Redis server but I’d like to use Docker to control it all.
2
Answers
You get this error because your volume configuration overwrites whatever you have in that path with the contents of your
.
directory, including the script that you add with thisCOPY --chown=node:node scripts/run.dev.sh ./run.dev.sh
(and earlier you hadWORKDIR /app
so this goes there).It’s an either-or situation and you need to decide. Either you copy something to the
/app
folder during the docker image building or you mount them during the container start.Currently your container seems to be configured much more in a style that expects no mount overriding, since you create a separate user to the image and all, which – while a good practice for production – might mess up the permissions anyway for live reloading.
So your only option (if you want live reload) is to remove basically everything from the dockerfile that adds anything to
/app
, and if those operations are still needed afterwards, you create a startup script that does those and run that on the container start so that they are executed on the files of the volume.Does your script work from the folder it currently is in? If it does, you run it from there. If it does not, you move it out of the folder permanently and run it the same way as before.
You can use Docker to only run the dependencies, and ordinary host tools for your main program.
If you run
then only the Redis container will start, but not the main application. Since you have published
ports:
in the Compose file, you can reconfigure your application to talk tolocalhost:6379
as the location of the Redis server (using the firstports:
number).From there, if you have access to a POSIX shell, you can run the
run.dev.sh
script, or you can manually run the SQLite migrations and the main applicationIf you do ultimately want to deploy this in a container, it’s common practice to run a separate database container rather than SQLite, and you could use a container database in combination with host code the same way as here. It’s also important to delete the
volumes:
in the Compose file so that you’re using the code built into the image, both for integration testing and final deployment, and to avoid irregularities like what you describe in the question.