Saya memiliki aplikasi dengan layanan berikut:
web/
- memegang dan menjalankan server web python 3 flask pada port 5000. Menggunakan sqlite3.worker/
- Memilikiindex.js
file yang merupakan pekerja untuk antrian. server web berinteraksi dengan antrian ini menggunakan json API over port9730
. Pekerja menggunakan redis untuk penyimpanan. Pekerja juga menyimpan data secara lokal di folderworker/images/
Sekarang pertanyaan ini hanya menyangkut worker
.
worker/Dockerfile
FROM node:0.12
WORKDIR /worker
COPY package.json /worker/
RUN npm install
COPY . /worker/
docker-compose.yml
redis:
image: redis
worker:
build: ./worker
command: npm start
ports:
- "9730:9730"
volumes:
- worker/:/worker/
links:
- redis
Ketika saya menjalankan docker-compose build
, semuanya berfungsi seperti yang diharapkan dan semua modul npm diinstal /worker/node_modules
seperti yang saya harapkan.
npm WARN package.json unfold@1.0.0 No README data
> phantomjs@1.9.2-6 install /worker/node_modules/pageres/node_modules/screenshot-stream/node_modules/phantom-bridge/node_modules/phantomjs
> node install.js
<snip>
Tetapi ketika saya melakukannya docker-compose up
, saya melihat kesalahan ini:
worker_1 | Error: Cannot find module 'async'
worker_1 | at Function.Module._resolveFilename (module.js:336:15)
worker_1 | at Function.Module._load (module.js:278:25)
worker_1 | at Module.require (module.js:365:17)
worker_1 | at require (module.js:384:17)
worker_1 | at Object.<anonymous> (/worker/index.js:1:75)
worker_1 | at Module._compile (module.js:460:26)
worker_1 | at Object.Module._extensions..js (module.js:478:10)
worker_1 | at Module.load (module.js:355:32)
worker_1 | at Function.Module._load (module.js:310:12)
worker_1 | at Function.Module.runMain (module.js:501:10)
Ternyata tidak ada modul yang ada di /worker/node_modules
(di host atau di wadah).
Jika di tuan rumah, saya npm install
, maka semuanya bekerja dengan baik. Tetapi saya tidak ingin melakukan itu. Saya ingin wadah untuk menangani dependensi.
Apa yang salah di sini?
(Tak perlu dikatakan, semua paket sudah masuk package.json
.)
volumes: - worker/:/worker/
blokir daridocker-compose.yml
file. Baris ini menimpa folder yang Anda buat dengan perintah COPY.When I run docker-compose build, everything works as expected and all npm modules are installed in /worker/node_modules as I'd expect.
- Bagaimana Anda memeriksa ini?Jawaban:
Ini terjadi karena Anda telah menambahkan
worker
direktori Anda sebagai volume ke Andadocker-compose.yml
, karena volume tidak dipasang selama pembuatan.Ketika buruh pelabuhan membangun gambar,
node_modules
direktori dibuat di dalamworker
direktori, dan semua dependensi diinstal di sana. Kemudian pada saat runtimeworker
direktori dari luar buruh pelabuhan dipasang ke instance buruh pelabuhan (yang tidak memiliki diinstalnode_modules
), menyembunyikannode_modules
Anda baru saja diinstal. Anda dapat memverifikasi ini dengan menghapus volume yang terpasang dari Andadocker-compose.yml
.Solusinya adalah dengan menggunakan volume data untuk menyimpan semua
node_modules
, karena volume data menyalin data dari gambar buruh pelabuhan yang dibangun sebelumworker
direktori dipasang. Ini bisa dilakukandocker-compose.yml
seperti ini:Saya tidak sepenuhnya yakin apakah ini menimbulkan masalah untuk portabilitas gambar, tetapi karena tampaknya Anda terutama menggunakan buruh pelabuhan untuk menyediakan lingkungan runtime, ini seharusnya tidak menjadi masalah.
Jika Anda ingin membaca lebih lanjut tentang volume, ada panduan pengguna yang bagus tersedia di sini: https://docs.docker.com/userguide/dockervolumes/
EDIT: Docker sejak itu mengubah sintaksinya untuk meminta yang terdepan
./
untuk pemasangan file relatif terhadap file docker-compose.yml.sumber
/worker/node_modules
tetap sama seperti sebelumnya (dengan dependensi lama). Apakah ada trik bagaimana cara menggunakan volume baru setelah membangun kembali gambar?docker-compose rm
tampaknya untuk memperbaiki masalah ini, tetapi saya percaya pasti ada solusi yang lebih baik dan lebih mudah.rebuild --no-cache
setiap kali deps berubah?The
node_modules
folder ditimpa oleh volume dan tidak ada lebih mudah diakses dalam wadah. Saya menggunakan strategi pemuatan modul asli untuk mengeluarkan folder dari volume:Dockerfile:
The
node_modules
direktori tidak dapat diakses dari luar wadah karena disertakan dalam gambar.sumber
node_modules
tidak dapat diakses dari luar wadah tetapi tidak benar-benar downside;)docker-compose run app npm install
Anda akan membuat node_modules di direktori saat ini dan Anda tidak perlu membangun kembali gambar.Solusi yang disediakan oleh @FrederikNS berfungsi, tetapi saya lebih suka untuk secara eksplisit memberi nama volume node_modules saya.
project/docker-compose.yml
File saya (versi docker-compose 1.6+):struktur file saya adalah:
Itu menciptakan volume bernama
project_node_modules
dan menggunakannya kembali setiap kali saya aplikasi saya.docker volume ls
Penampilan saya seperti ini:sumber
Baru-baru ini saya memiliki masalah yang sama. Anda dapat menginstal di
node_modules
tempat lain dan mengaturNODE_PATH
variabel lingkungan.Pada contoh di bawah ini saya instal
node_modules
ke/install
pekerja / Dockerfile
docker-compose.yml
sumber
node_modules
berdasarkan artikel ini . Tapi itu membuat saya mengalami masalah ini . Solusi ini di sini untuk membuat direktori terpisah untuk menyalin ke Andapackage.json
, jalankan dinpm install
sana, kemudian tentukanNODE_PATH
variabel lingkungandocker-compose.yml
untuk menunjuk kenode_modules
folder direktori yang berfungsi dan terasa benar.npm install
host? Tampaknyanode_modules
akan muncul di host dan akan direfleksikan ke wadah, mengambil prioritasNODE_PATH
. Jadi container akan menggunakan node_modules dari host.Ada solusi yang elegan:
Hanya memasang tidak seluruh direktori, tetapi hanya direktori aplikasi. Dengan cara ini Anda tidak akan mengalami kesulitan
npm_modules
.Contoh:
Dockerfile.dev:
sumber
UPDATE: Gunakan solusi yang disediakan oleh @FrederikNS.
Saya mengalami masalah yang sama. Ketika folder di
/worker
-mount ke wadah - semua kontennya akan disinkronkan (sehingga folder node_modules akan hilang jika Anda tidak memilikinya secara lokal.)Karena paket npm yang tidak kompatibel berdasarkan OS, saya tidak bisa hanya menginstal modul secara lokal - kemudian meluncurkan wadah, jadi ..
Solusi saya untuk ini, adalah dengan membungkus sumber dalam
src
folder, lalu menautkannode_modules
ke folder itu, menggunakan file index.js ini . Jadi,index.js
file tersebut sekarang menjadi titik awal aplikasi saya.Ketika saya menjalankan wadah, saya memasang
/app/src
folder kesrc
folder lokal saya .Jadi folder penampung terlihat seperti ini:
Itu jelek , tapi berhasil ..
sumber
Karena cara Node.js memuat modul ,
node_modules
bisa di mana saja di jalur ke kode sumber Anda. Misalnya, letakkan sumber Anda di/worker/src
danpackage.json
di Anda/worker
, begitu/worker/node_modules
juga di mana mereka diinstal.sumber
Menginstal node_modules dalam wadah ke berbeda dari folder proyek, dan pengaturan NODE_PATH ke folder node_modules membantu saya (Anda perlu membangun kembali wadah).
Saya menggunakan komposisi buruh pelabuhan. Struktur file proyek saya:
docker-compose.yml:
Dockerfile di folder nodejs:
sumber
NODE_PATH
adalah kunci untuk saya.CMD npm start
tidak menggunakan NODE_PATH yang ditentukan.Ada juga beberapa solusi sederhana tanpa memetakan
node_module
direktori ke volume lain. Ini akan pindah menginstal paket npm ke perintah CMD akhir.pekerja / Dockerfile
docker-compose.yml
sumber
Ada dua persyaratan terpisah yang saya lihat untuk lingkungan dev node ... mount kode sumber Anda ke dalam wadah, dan mount node_modules DARI wadah (untuk IDE Anda). Untuk mencapai yang pertama, Anda melakukan mount biasa, tetapi tidak semuanya ... hanya hal-hal yang Anda butuhkan
(Alasan untuk tidak melakukan
- /worker/node_modules
ini adalah karena docker-compose akan mempertahankan volume di antara run, yang berarti Anda dapat menyimpang dari apa yang sebenarnya ada dalam gambar (mengalahkan tujuan tidak hanya mengikat pemasangan dari host Anda)).Yang kedua sebenarnya lebih sulit. Solusi saya agak retas, tetapi berhasil. Saya memiliki skrip untuk menginstal folder node_modules pada mesin host saya, dan saya hanya harus ingat untuk memanggilnya setiap kali saya memperbarui package.json (atau, tambahkan ke target make yang menjalankan build docker-compose build secara lokal).
sumber
Menurut pendapat saya, kita tidak boleh
RUN npm install
di Dockerfile. Sebagai gantinya, kita dapat memulai sebuah wadah menggunakan bash untuk menginstal dependensi sebelum menjalankan layanan simpul formalsumber
node_modules
tetap gigih bahkan setelah wadah dikeluarkan, Anda juga harus tahu kapan atau kapan tidak melakukannyanpm install
secara manual. OP menyarankan untuk melakukannya pada setiap build gambar . Anda dapat melakukannya, tetapi Anda tidak perlu juga menggunakan volume untuk itu. Pada setiap build, modul akan menjadi yang terbaru.Anda dapat mencoba sesuatu seperti ini di Dockerfile Anda:
Maka Anda harus menggunakan Volume seperti ini:
Skrip awal harus menjadi bagian dari repositori pekerja Anda dan terlihat seperti ini:
Jadi node_modules adalah bagian dari volume pekerja Anda dan akan disinkronkan dan skrip npm dieksekusi ketika semuanya habis.
sumber
Anda juga dapat membuang Dockerfile Anda, karena kesederhanaannya, cukup gunakan gambar dasar dan tentukan perintah dalam file penulisan Anda:
Ini sangat berguna bagi saya, karena saya hanya perlu lingkungan gambar, tetapi beroperasi pada file saya di luar wadah dan saya pikir ini adalah apa yang ingin Anda lakukan juga.
sumber