docker-nginx-react

Dockerfile#

برای شروع ابتدا باید یک Dockerfile ( دقیقا با همین نام ) در فولدر اصلی پروژه بسازیم و کد های زیر را در آن استفاده کنیم:

FROM node:14.17.3-alpine3.14
WORKDIR /hami-dashboard
ENV PATH="./node_modules/.bin:$PATH"
COPY . ./
RUN npm install
RUN npm run build
RUN npm rebuild node-sass
CMD ["npm", "start"]
EXPOSE 3010

FROM: بسته به ورژن استفاده شده node در هنگام ساخت پروژه، ورژن آن را مقابل FROM می نویسیم ( حتما قبل از آن باید در سایت hub.docker.com چک کنیم ک ورژن نوشته شده، موجود باشد ).

WORKDIR: مسیر فولدر اصلی پروژه می باشد ک Dockerfile در آن می باشد.

ENV PATH: مسیر ماژول های استفاده شده می باشد ک برای JS باید مسیر node_modules داده شود.

COPY: آرگومان اول مسیر و نام فایل مورد نظر می باشد و آرگومان دوم مسیر فولدر مورد نظر در داکر می باشد ( فایل ها کپی می شوند و در داکر الصاق می شوند ). در واقع نقطه دوم همان WORKDIR می باشد.

RUN: دستور های مورد نیاز را در این قسمت قرار می دهیم تا بعد از کپی شدن، اجرا شوند.

CMD: آخرین دستور مورد نیاز برای اجرا شدن برنامه می باشد ک باید آرایه ای از کلمات ( مثلا دستور بالا موقع اجرا شدن به npm start تبدیل می شود ).

EXPOSE: پورت مورد نظر برای اجرا شدن برنامه را مشخص می کنیم.

🎉 حال توسط دستور زیر می توان Dockerfile را اجرا کنیم:

docker build --tag hami-dashboard .

که tag نام image ساخته شده را تعیین می کند و نقطه ( . ) مسیر ساخت image می باشد.

ساخت کانتینر#

حال توسط دستور زیر container مورد نظر را بر اساس image ساخته شده می سازیم و اجرا می کنیم:

docker run --name hami-dashboard -p 3010:3000 -d hami-dashboard

name: که اسم بعد از پرچم name در واقع نام container ما می باشد و می تواند نامی متفاوت از نام image باشد

-p: ( مخفف publish می باشد ) در واقع نشانگر و تعیین کننده port می باشد و 2 آرگومان دارد ک آرگومان اول port دلخواه ما می باشد ک می خواهیم app را با آن پورت ببینیم و دومی پورت اصلی app ما می باشد ک react به صورت پیش فرض از پورت 3000 استفاده می کند.

-d: نشانگر detach شدن می باشد یعنی اگر بخواهیم بعد از ساخت container، بخواهیم به کارمان ادامه دهیم از این پرچم استفاده می کنیم.

و بعد از -d نام image ساخته شده را باید درست وارد کنیم.

docker-compose#

برای بهتر کردن اجرا شدن dockerFile و هم چنین اجرا چند Service و چند app همزمان با هم از docker-compose استفاده می کنیم و همچنین به ما این امکان را می دهد که image هایمان را راحت تر انتقال دهیم

که برای react می توان از کد زیر استفاده کرد:

version: "3.9"
services:
hdreact:
build:
context: .
volumes:
- .:/hami-dashboard
ports:
- 3010:3000
image: hdreact:react
container_name: hami-dashboard
stdin_open: true
# command: npm start
restart: unless-stopped
# networks:
# - app-network

version: در واقع ورژن خود docker-compose می باشد.

services: لیست سرویس های ما می باشند که هر سرویس باید یک نام داشته باشد.

hdreact: نام service ما می باشد که تمامی موارد مربوط به این سرویس باید زیر آن با فاصله قرار بگیرد.( نام دلخواه می باشد. )

build: مسیر و نام dockerFile خود را قرار می دهیم که در اینجا برای مسیردهی از context استفاده می کنیم و آدرس dockerFile را می دهیم.

volumes: مسیر فایل هایی که می خواهیم به صورت داینامیک تغییرات را اعمال کنند، مشخص می کنیم. یعنی در کد های داخل سیستم هر تغییری ایجاد شود، در داکر نیز تغییر اعمال شود. ( در اینجا کل فایل پروژه می باشد )

ports: می توان برای هر پورت app مان یک پورت جایگزین قرار دهیم تا در داکر با یک پورت دیگر اجرا شود.( سمت چپ پورت دلخواهمان که می خواهیم اشغال شود و سمت راست پورت app مان می باشد که داخل داکر اجرا می شود، یعنی پورت 3000 را به 3010 عوض کن. )

image: یک نام دلخواه برای image مان می باشد که بهتر است هم نام service مان باشد.( که اولی نام image و دومی tag آن می باشد )

container_name: یک نام دلخواه برای کانتینر مان می باشد.

stdin_open: مربوط به react می باشد که با هر تغییر سریع صفحه رفرش شود.

command: به جای CMD در dockerFile، می توان در docker-compose هم از آن استفاده کرد.

restart: توسط این دستور، کانتینری که استاپ می شود، دوباره restart می شود، به صورت خودکار.

networks: توسط این دستور می توان service های مختلف را در یک کانتینر با network های مختلف استفاده کرد، برای مثال می توان در 2 نتورک مختلف در یک کانتینر از یک port استفاده کرد ( مثلا 80 ) و چون network ها با هم متفاوت هستند هر 2 پورت کار میکنند.

🎉 فاصله ها در docker-compose بسیار مهم می باشد.

حال توسط دستور زیر می توان پروژه را build می کنیم و همزمان اجرا نیز می شود:

docker-compose up -d

موارد اضافه#

🎉 توسط دستور زیر می توان لیست image ها را دید:

docker images

🎉 میتوان برای کپی نکردن فایل ها و فولدر هایی ک نیاز نداریم یک فایل dockerignore. بسازیم و مانند کد زیر نام فایل ها و فولدر های غیر ضروری را بنویسیم:

node_modules
Dockerfile
Dockerfile.prod
.git
.dockerignore
.gitignore
.env
*.tar

🎉 می توان توسط دستور زیر ( هنگامی که image داریم) دوباره پروژه را rebuild کنیم:

docker-compose up -d --force-recreate --build

مهم: همیشه سعی شود اول package.json را کپی و سپس نصب کنیم ( در داکرفایل )، زیرا ما خیلی کم فایل package.json را تغییر می دهیم و اگر آن را به داکر فایل اضافه نکنیم، هر بار ک کد های مثلا src را تغییر دهیم، دوباره npm install اجرا می شود.

برای حذف یک image خاص می توان از دستور زیر استفاده کرد:( برای بدست آوردن کد هر image میتوان از docker image ls استفاده کرد )

docker image rm 26sadf564

در واقع ما برای اینکه اپپ مان از دنیای بیرون هم به آن دسترسی داشته باشیم ( مثلا بقیه سیستم هایی که به اینترنت ما متصل هستند ) آن را ببینند باید برای آن پورت تعیین شود و مشخص شود که چ پورتی از دنیای داخل داکر باید اطلاعات را به چ پورتی از دنیای بیرون بفرستد.

برای اینکه یک کانتینر را ببینیم از دستور docker ps و برای متوقف کردن و حذف یک کانتینر ک در حال اجرا است از دستور docker rm react-app -f استفاده می کنیم

همیشه عدد سمت راست : عددی است ک مربوط به خود docker می باشد و عدد سمت چپ : همیشه مربوط به لوکال ماشین ما می باشد، مثل ویندوز و سیستم هایی ک به اینترنت ما متصل هستند. یعنی مثلا هرکسی در اینترنت من ( local machine ) با 3010 میتواند اطلاعات بفرستد یا بگیرد و داکر هم این درخواست ها را به درگاه 3000 انتقال می دهد ک در این مثال، react میباشد.

دستور docker exec -it react-app bash در واقع محیط bash را در کانتینر مربوطه باز می کند.

nginx and docker-compose#

🎉 می توان توسط کانفیگ زیر در docker-compose از 2 سرویس مجزا مانند node و nginx همزمان برای یک کانتینر خاص استفاده کرد:

version: "3"
services:
hdreact:
build:
context: .
volumes:
- .:/hami-dashboard
ports:
- 8081:8081
image: hdreact:react
container_name: hami-dashboard
stdin_open: true
# environment:
# SERVICE_NAME: node
# SERVICE_TAGS: react
# command: npm start
environment:
NODE_ENV: production
restart: unless-stopped
#Nginx Service
webserver:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
tty: true
ports:
- "4000:8081"
# - "443:443"
# - "9001-9009:9001-9009"
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
# networks:
# - app-network

🎉 همچنین می توان از کانفیگ dockerFile زیر نیز استفاده کرد برای مچ کردن آن با docker-compose و همچنین بخش stage 2 نیز می توان برای nginx در داکرفایل استفاده کرد ک کامنت می باشد، اما بهتر است ک در docker-compose باشد.

# stage1 - build react app first
FROM node:14.17.3-alpine3.14 as build
WORKDIR /hami-dashboard
ENV PATH=/node_modules/.bin:$PATH
COPY package.json ./
RUN npm install
RUN npm rebuild node-sass
COPY . ./
# RUN npm run build
# CMD [ "npm", "run", "build" ]
#COPY build ./
# stage 2 - build the final image and copy the react build files
# FROM nginx:1.17.8-alpine
# # COPY --from=build /hami-dashboard/build /usr/share/nginx/html
# COPY --from=build /hami-dashboard/build /var/www/
# # COPY --from=build /hami-dashboard/nginx/nginx.conf /etc/nginx/conf.d/default.conf
# RUN rm /etc/nginx/conf.d/default.conf
# COPY nginx/nginx.conf /etc/nginx/conf.d
# CMD ["nginx", "-g", "daemon off;"]
EXPOSE 8081