skip to Main Content

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


  1. 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 this COPY --chown=node:node scripts/run.dev.sh ./run.dev.sh (and earlier you had WORKDIR /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.

    Login or Signup to reply.
  2. I want hmr/live-reloading to work with remix. […] I need Redis which isn’t directly available in Windows.

    You can use Docker to only run the dependencies, and ordinary host tools for your main program.

    If you run

    docker-compose up -d redis
    

    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 to localhost:6379 as the location of the Redis server (using the first ports: 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 application

    export DB_PATH=../../data/affiliates.dev.sqlite
    pnpm db:migrate:dev  # if needed
    pnpm dev
    

    If 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search