Konteneryzacja aplikacji i katalogu zależności przy klonowaniu repozytorium

1

Cześć wszystkim, przychodzę z zapytaniem dotyczącym pracy z aplikacją Next.js działającą w Dockerze. Mam nadzieję, że uda mi się przedstawić proces zrozumiale 😉

Cele: wygenerować nową aplikację i przygotować lokalne środowisko dev w oparciu o kontenery Dockera.

Chcę, aby inne osoby mogły sklonować repozytorium Git, uruchomić aplikację Next.js i nad nią pracować. Udało mi się to zrobić. Zastanawia mnie jednak kwestia tworzenie katalogu node_modules za pomocą polecenia npm install, ale po kolei. W punktach opiszę proces (pominąłem polecenia Git, bo nie wnoszą nic istotnego do sprawy).

  1. Utworzyłem strukturę projektu:
project/
├─ next-app/
├─ .dockerignore
├─ app.Dockerfile
├─ create-app.Dockerfile
├─ docker-compose.yaml
├─ README.md

.dockerignore:

node_modules
*.Dockerfile
Dockerfile
docker-compose.yaml

app.Dockerfile

FROM node:20.5.1-alpine3.18

WORKDIR /next-app

COPY ./next-app/package*.json .

RUN npm install

COPY ./next-app .

CMD ["npm", "run", "dev"]

create-app.Dockerfile

FROM node:20.5.1-alpine3.18

WORKDIR /next-app

CMD ["sh"]

docker-compose.yaml

version: "3.9"

services:
  app:
    container_name: app
    build:
      context: .
      dockerfile: app.Dockerfile
    ports:
      - "3000:3000"
    volumes:
      - ./next-app:/next-app
  1. Utworzyłem obraz do przygotowania kontenera, dzięki któremu można wygenerować nową aplikację Next.js (tak właściwie, to dowolną aplikację Node.js):
docker build --file create-app.Dockerfile --tag create-app:1.0.0 .
  1. Utworzyłem kontener:
docker run --name create-app --rm --volume ${PWD}/next-app:/next-app -it create-app:1.0.0
  1. Wewnątrz kontenera wygenerowałem nową aplikację Next.js. Jako nazwę projektu wpisałem znak . i wybrałem domyślne opcje.
npx create-next-app@latest --use-npm

Tak wygląda wynik końcowy:

/next-app # npx create-next-app@latest --use-npm
Need to install the following packages:
  [email protected]
Ok to proceed? (y) y
✔ What is your project named? … .
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias? … No / Yes
Creating a new Next.js app in /next-app.

Using npm.

Initializing project with template: app-tw


Installing dependencies:
- react
- react-dom
- next
- typescript
- @types/react
- @types/node
- @types/react-dom
- tailwindcss
- postcss
- autoprefixer
- eslint
- eslint-config-next


added 329 packages, and audited 330 packages in 43s

117 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Success! Created next-app at /next-app

npm notice
npm notice New patch version of npm available! 9.8.0 -> 9.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.8.1
npm notice Run npm install -g [email protected] to update!
npm notice
/next-app #
  1. Zamknąłem kontener:
/next-app # exit
  1. Utworzyłem obraz aplikacji. Użyłem narzędzia docker compose, ponieważ wygodnie się z tym programem pracuje.
docker compose build --no-cache
  1. Uruchomiłem kontener z aplikacją:
docker compose up -d
  1. Otworzyłem w przeglądarce adres http://localhost:3000, pod którym dostępna jest nowa aplikacja Next.js.

  2. Mogę edytować kod za pomocą VSCode, zmiany są widocznie.

Podsumowując na tym etapie wszystko wydaje się być ok. Jednak problem pojawia się, gdy sklonuję repozytorium i spróbuję uruchomić aplikację. Już wyjaśniam o co dokładnie chodzi. W punktach opiszę proces.

  1. Utworzyłem obraz aplikacji za pomocą narzędzia docker compose:
docker compose build --no-cache
  1. Uruchomiłem kontener z aplikacją:
docker compose up -d
  1. Kontener został zamknięty ze statusem Exit 127, więc sprawdziłem logi:
docker compose logs -f

Logi z kontenera:

app  |
app  |
app  | > [email protected] dev
app  | > next dev
app  |
app  |
app  | sh: next: not found
  1. W VSCode sprawdziłem zawartość katalogu project/next-app i dostrzegłem, że nie ma katalogu node_modules. Problem ten rozwiązałem w kolejnych punktach.

  2. Utworzyłem kontener:

docker run --name create-app --rm --volume ${PWD}/next-app:/next-app -it create-app:1.0.0
  1. Wewnątrz kontenera zainstalowałem pakiety za pomocą npm:
/next-app # npm install
  1. Zamknąłem kontener:
/next-app # exit
  1. Tym razem katalog node_modules jest dostępny. Uruchomiłem kontener z aplikacją:
docker compose up -d
  1. Mogę edytować kod za pomocą VSCode, zmiany są widocznie.

Tutaj pojawia się pytanie:

Dlaczego po skolonowaniu repozytorium, zbudowaniu obrazu i uruchomieniu kontenera, katalog node_modules nie został utworzony skoro w pliku app.Dockerfile znajduje się wywołanie polecenia npm install? 🤔

1

@witcher1: Po wypróbowaniu kilku nietrafionych pomysłów, przyszedł mi do głowy jeszcze jeden - aktualnie nie ma mnie w domu żeby go sprawdzić - może problemem jest to, ze docker-compose robi mounta po zbudowaniu obrazu? Totalnie nie mam pojęcia, strzelam.
Spróbuj zbudować obraz za pomocą komendy docker build zamiast używać docker-compose i daj znać.

0

Czy w wolnej chwili możesz podzielić się tymi pomysłami i sprawdzić ten jeszcze jeden?

0

Zrobiłem pobieżny research i jak się okazuje prawdopodobnie problemem jest podpinanie i mapowanie (host:container) volume, które zawiera kod aplikacji i katalog node_modules. Na stackoverflow ludzie podawali jakieś rozwiązania - na szybko sprawdziłem jedno z nich i nie pomogło. Niemniej problem wydaje się raczej popularny i może uda się go elegancko rozwiązać. Niestety ogranicza mnie na razie brak konkretnej wiedzy o Dockerze, aby wiedzieć czego szukać. Jutro może ze świeżą głową pójdzie lepiej 😞

0

@witcher1: Dobra, jest tak jak napisałem.
Mountowanie volume'ów działa w momencie uruchamiania kontenera, nie ma opcji zrobić tego w fazie budowania obrazów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1