ಓಪನ್‌ಶಿಫ್ಟ್‌ನಲ್ಲಿನ ಆಧುನಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಭಾಗ 2: ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳು

ಎಲ್ಲರಿಗು ನಮಸ್ಖರ! Red Hat OpenShift ನಲ್ಲಿ ಆಧುನಿಕ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹೇಗೆ ನಿಯೋಜಿಸಬೇಕು ಎಂಬುದನ್ನು ನಾವು ತೋರಿಸುವ ನಮ್ಮ ಸರಣಿಯಲ್ಲಿ ಇದು ಎರಡನೇ ಪೋಸ್ಟ್ ಆಗಿದೆ.

ಓಪನ್‌ಶಿಫ್ಟ್‌ನಲ್ಲಿನ ಆಧುನಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಭಾಗ 2: ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳು

ಹಿಂದಿನ ಪೋಸ್ಟ್‌ನಲ್ಲಿ, ಓಪನ್‌ಶಿಫ್ಟ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ಆಧುನಿಕ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಮತ್ತು ನಿಯೋಜಿಸಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾದ ಹೊಸ S2I (ಮೂಲದಿಂದ ಚಿತ್ರಕ್ಕೆ) ಬಿಲ್ಡರ್ ಚಿತ್ರದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ನಾವು ಸ್ವಲ್ಪ ಸ್ಪರ್ಶಿಸಿದ್ದೇವೆ. ನಂತರ ನಾವು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ತ್ವರಿತವಾಗಿ ನಿಯೋಜಿಸುವ ವಿಷಯದಲ್ಲಿ ಆಸಕ್ತಿ ಹೊಂದಿದ್ದೇವೆ ಮತ್ತು ಇಂದು ನಾವು S2I ಚಿತ್ರವನ್ನು "ಶುದ್ಧ" ಬಿಲ್ಡರ್ ಚಿತ್ರವಾಗಿ ಹೇಗೆ ಬಳಸುವುದು ಮತ್ತು ಸಂಬಂಧಿತ OpenShift ಅಸೆಂಬ್ಲಿಗಳೊಂದಿಗೆ ಸಂಯೋಜಿಸುವುದು ಹೇಗೆ ಎಂದು ನೋಡೋಣ.

ಕ್ಲೀನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರ

ನಾವು ಭಾಗ XNUMX ರಲ್ಲಿ ಹೇಳಿದಂತೆ, ಹೆಚ್ಚಿನ ಆಧುನಿಕ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬಿಲ್ಡ್ ಸ್ಟೇಜ್ ಎಂದು ಕರೆಯಲ್ಪಡುತ್ತವೆ, ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಕೋಡ್ ಟ್ರಾನ್ಸ್‌ಪಿಲೇಶನ್, ಬಹು ಫೈಲ್ ಕಾನ್ಕಾಟೆನೇಶನ್ ಮತ್ತು ಮಿನಿಫಿಕೇಶನ್‌ನಂತಹ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ಈ ಕಾರ್ಯಾಚರಣೆಗಳ ಪರಿಣಾಮವಾಗಿ ಪಡೆದ ಫೈಲ್ಗಳು - ಮತ್ತು ಇದು ಸ್ಥಿರ HTML, JavaScript ಮತ್ತು CSS - ಔಟ್ಪುಟ್ ಫೋಲ್ಡರ್ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿದೆ. ಈ ಫೋಲ್ಡರ್‌ನ ಸ್ಥಳವು ಸಾಮಾನ್ಯವಾಗಿ ಯಾವ ಬಿಲ್ಡ್ ಟೂಲ್‌ಗಳನ್ನು ಬಳಸಲಾಗುತ್ತಿದೆ ಎಂಬುದರ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿರುತ್ತದೆ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆಗಾಗಿ ಇದು ./ಬಿಲ್ಡ್ ಫೋಲ್ಡರ್ ಆಗಿರುತ್ತದೆ (ನಾವು ಇದನ್ನು ಕೆಳಗೆ ಹೆಚ್ಚು ವಿವರವಾಗಿ ಹಿಂತಿರುಗಿಸುತ್ತೇವೆ).

ಮೂಲದಿಂದ ಚಿತ್ರ (S2I)

ಈ ಪೋಸ್ಟ್‌ನಲ್ಲಿ ನಾವು “S2I ಎಂದರೇನು ಮತ್ತು ಅದನ್ನು ಹೇಗೆ ಬಳಸುವುದು” ಎಂಬ ವಿಷಯವನ್ನು ಸ್ಪರ್ಶಿಸುವುದಿಲ್ಲ (ನೀವು ಇದರ ಬಗ್ಗೆ ಇನ್ನಷ್ಟು ಓದಬಹುದು ಇಲ್ಲಿ), ಆದರೆ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರವು ಏನು ಮಾಡುತ್ತದೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಈ ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ ಎರಡು ಹಂತಗಳ ಬಗ್ಗೆ ಸ್ಪಷ್ಟವಾಗಿರುವುದು ಮುಖ್ಯವಾಗಿದೆ.

ಅಸೆಂಬ್ಲಿ ಹಂತ

ಅಸೆಂಬ್ಲಿ ಹಂತವು ನೀವು ಡಾಕರ್ ಬಿಲ್ಡ್ ಅನ್ನು ರನ್ ಮಾಡಿದಾಗ ಮತ್ತು ಹೊಸ ಡಾಕರ್ ಇಮೇಜ್‌ನೊಂದಿಗೆ ಕೊನೆಗೊಂಡಾಗ ಏನಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ಹೋಲುತ್ತದೆ. ಅಂತೆಯೇ, ಓಪನ್‌ಶಿಫ್ಟ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ನಿರ್ಮಾಣವನ್ನು ಪ್ರಾರಂಭಿಸುವಾಗ ಈ ಹಂತವು ಸಂಭವಿಸುತ್ತದೆ.

ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರದ ಸಂದರ್ಭದಲ್ಲಿ, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ನ ಅವಲಂಬನೆಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಮತ್ತು ನಿರ್ಮಾಣವನ್ನು ಚಲಾಯಿಸಲು ಇದು ಜವಾಬ್ದಾರವಾಗಿರುತ್ತದೆ. ಸ್ಕ್ರಿಪ್ಟ್ ಅನ್ನು ಜೋಡಿಸಿ. ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ, ಬಿಲ್ಡರ್ ಚಿತ್ರವು npm ರನ್ ಬಿಲ್ಡ್ ಸ್ಟ್ರಕ್ಟ್ ಅನ್ನು ಬಳಸುತ್ತದೆ, ಆದರೆ ಇದನ್ನು NPM_BUILD ಪರಿಸರ ವೇರಿಯಬಲ್ ಮೂಲಕ ಅತಿಕ್ರಮಿಸಬಹುದು.

ನಾವು ಮೊದಲೇ ಹೇಳಿದಂತೆ, ಸಿದ್ಧಪಡಿಸಿದ, ಈಗಾಗಲೇ ನಿರ್ಮಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ನ ಸ್ಥಳವು ನೀವು ಯಾವ ಸಾಧನಗಳನ್ನು ಬಳಸುತ್ತೀರಿ ಎಂಬುದರ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿರುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, React ಸಂದರ್ಭದಲ್ಲಿ ಇದು ./build ಫೋಲ್ಡರ್ ಆಗಿರುತ್ತದೆ ಮತ್ತು ಕೋನೀಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಇದು project_name/dist ಫೋಲ್ಡರ್ ಆಗಿರುತ್ತದೆ. ಮತ್ತು, ಹಿಂದಿನ ಪೋಸ್ಟ್‌ನಲ್ಲಿ ಈಗಾಗಲೇ ತೋರಿಸಿರುವಂತೆ, ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ ನಿರ್ಮಿಸಲು ಹೊಂದಿಸಲಾದ ಔಟ್‌ಪುಟ್ ಡೈರೆಕ್ಟರಿಯ ಸ್ಥಳವನ್ನು OUTPUT_DIR ಪರಿಸರ ವೇರಿಯಬಲ್ ಮೂಲಕ ಅತಿಕ್ರಮಿಸಬಹುದು. ಸರಿ, ಔಟ್‌ಪುಟ್ ಫೋಲ್ಡರ್‌ನ ಸ್ಥಳವು ಫ್ರೇಮ್‌ವರ್ಕ್‌ನಿಂದ ಫ್ರೇಮ್‌ವರ್ಕ್‌ಗೆ ಭಿನ್ನವಾಗಿರುವುದರಿಂದ, ನೀವು ರಚಿಸಿದ ಔಟ್‌ಪುಟ್ ಅನ್ನು ಚಿತ್ರದಲ್ಲಿನ ಪ್ರಮಾಣಿತ ಫೋಲ್ಡರ್‌ಗೆ ನಕಲಿಸುತ್ತೀರಿ, ಅವುಗಳೆಂದರೆ /opt/apt-root/output. ಈ ಲೇಖನದ ಉಳಿದ ಭಾಗವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಇದು ಮುಖ್ಯವಾಗಿದೆ, ಆದರೆ ಇದೀಗ ಮುಂದಿನ ಹಂತವನ್ನು ತ್ವರಿತವಾಗಿ ನೋಡೋಣ - ರನ್ ಹಂತ.

ರನ್ ಹಂತ

ಅಸೆಂಬ್ಲಿ ಹಂತದಲ್ಲಿ ರಚಿಸಲಾದ ಹೊಸ ಚಿತ್ರದ ಮೇಲೆ ಡಾಕರ್ ರನ್ಗೆ ಕರೆ ಮಾಡಿದಾಗ ಈ ಹಂತವು ಸಂಭವಿಸುತ್ತದೆ. ಓಪನ್‌ಶಿಫ್ಟ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ನಿಯೋಜಿಸುವಾಗ ಅದೇ ಸಂಭವಿಸುತ್ತದೆ. ಡೀಫಾಲ್ಟ್ ಸ್ಕ್ರಿಪ್ಟ್ ರನ್ ಮಾಡಿ ಉಪಯೋಗಿಸುತ್ತದೆ ಸರ್ವ್ ಮಾಡ್ಯೂಲ್ ಮೇಲಿನ ಪ್ರಮಾಣಿತ ಔಟ್‌ಪುಟ್ ಡೈರೆಕ್ಟರಿಯಲ್ಲಿರುವ ಸ್ಥಿರ ವಿಷಯವನ್ನು ಪೂರೈಸಲು.

ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ತ್ವರಿತವಾಗಿ ನಿಯೋಜಿಸಲು ಈ ವಿಧಾನವು ಉತ್ತಮವಾಗಿದೆ, ಆದರೆ ಸ್ಥಿರ ವಿಷಯವನ್ನು ಈ ರೀತಿ ನೀಡಲು ಸಾಮಾನ್ಯವಾಗಿ ಶಿಫಾರಸು ಮಾಡುವುದಿಲ್ಲ. ಒಳ್ಳೆಯದು, ವಾಸ್ತವದಲ್ಲಿ ನಾವು ಸ್ಥಿರ ವಿಷಯವನ್ನು ಮಾತ್ರ ಒದಗಿಸುತ್ತೇವೆ, ನಮ್ಮ ಚಿತ್ರದೊಳಗೆ Node.js ಅನ್ನು ಸ್ಥಾಪಿಸುವ ಅಗತ್ಯವಿಲ್ಲ - ವೆಬ್ ಸರ್ವರ್ ಸಾಕು.

ಬೇರೆ ರೀತಿಯಲ್ಲಿ ಹೇಳುವುದಾದರೆ, ಜೋಡಿಸುವಾಗ ನಮಗೆ ಒಂದು ವಿಷಯ ಬೇಕು, ಕಾರ್ಯಗತಗೊಳಿಸುವಾಗ ನಮಗೆ ಇನ್ನೊಂದು ಬೇಕು. ಈ ಪರಿಸ್ಥಿತಿಯಲ್ಲಿ, ಚೈನ್ಡ್ ನಿರ್ಮಾಣಗಳು ಸೂಕ್ತವಾಗಿ ಬರುತ್ತವೆ.

ಚೈನ್ಡ್ ನಿರ್ಮಾಣಗಳು

ಇದನ್ನೇ ಅವರು ಬರೆಯುತ್ತಾರೆ ಚೈನ್ಡ್ ನಿರ್ಮಾಣಗಳು OpenShift ದಾಖಲಾತಿಯಲ್ಲಿ:

"ಎರಡು ಅಸೆಂಬ್ಲಿಗಳನ್ನು ಒಟ್ಟಿಗೆ ಜೋಡಿಸಬಹುದು, ಒಂದು ಸಂಕಲನ ಘಟಕವನ್ನು ಉತ್ಪಾದಿಸುತ್ತದೆ ಮತ್ತು ಇನ್ನೊಂದು ಆ ಘಟಕವನ್ನು ಚಲಾಯಿಸಲು ಬಳಸಲಾಗುವ ಪ್ರತ್ಯೇಕ ಚಿತ್ರದಲ್ಲಿ ಆ ಘಟಕವನ್ನು ಹೋಸ್ಟ್ ಮಾಡುತ್ತದೆ."

ಬೇರೆ ರೀತಿಯಲ್ಲಿ ಹೇಳುವುದಾದರೆ, ನಮ್ಮ ಬಿಲ್ಡ್ ಅನ್ನು ರನ್ ಮಾಡಲು ನಾವು ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರವನ್ನು ಬಳಸಬಹುದು ಮತ್ತು ನಂತರ ನಮ್ಮ ವಿಷಯವನ್ನು ಪೂರೈಸಲು ವೆಬ್ ಸರ್ವರ್ ಇಮೇಜ್ ಅನ್ನು ಅದೇ NGINX ಅನ್ನು ಬಳಸಬಹುದು.

ಹೀಗಾಗಿ, ನಾವು ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರವನ್ನು "ಶುದ್ಧ" ಬಿಲ್ಡರ್ ಆಗಿ ಬಳಸಬಹುದು ಮತ್ತು ಅದೇ ಸಮಯದಲ್ಲಿ ಸಣ್ಣ ರನ್ಟೈಮ್ ಇಮೇಜ್ ಅನ್ನು ಹೊಂದಬಹುದು.

ಈಗ ಇದನ್ನು ನಿರ್ದಿಷ್ಟ ಉದಾಹರಣೆಯೊಂದಿಗೆ ನೋಡೋಣ.

ತರಬೇತಿಗಾಗಿ ನಾವು ಬಳಸುತ್ತೇವೆ ಸರಳ ಪ್ರತಿಕ್ರಿಯೆ ಅಪ್ಲಿಕೇಶನ್, create-react-app ಕಮಾಂಡ್ ಲೈನ್ ಉಪಕರಣವನ್ನು ಬಳಸಿಕೊಂಡು ರಚಿಸಲಾಗಿದೆ.

ಎಲ್ಲವನ್ನೂ ಒಟ್ಟುಗೂಡಿಸಲು ಇದು ನಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ OpenShift ಟೆಂಪ್ಲೇಟ್ ಫೈಲ್.

ಈ ಫೈಲ್ ಅನ್ನು ಹೆಚ್ಚು ವಿವರವಾಗಿ ನೋಡೋಣ ಮತ್ತು ನಿಯತಾಂಕಗಳ ವಿಭಾಗದೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸೋಣ.

parameters:
  - name: SOURCE_REPOSITORY_URL
    description: The source URL for the application
    displayName: Source URL
    required: true
  - name: SOURCE_REPOSITORY_REF
    description: The branch name for the application
    displayName: Source Branch
    value: master
    required: true
  - name: SOURCE_REPOSITORY_DIR
    description: The location within the source repo of the application
    displayName: Source Directory
    value: .
    required: true
  - name: OUTPUT_DIR
    description: The location of the compiled static files from your web apps builder
    displayName: Output Directory
    value: build
    required: false

ಇಲ್ಲಿ ಎಲ್ಲವೂ ಬಹಳ ಸ್ಪಷ್ಟವಾಗಿದೆ, ಆದರೆ OUTPUT_DIR ಪ್ಯಾರಾಮೀಟರ್ಗೆ ಗಮನ ಕೊಡುವುದು ಯೋಗ್ಯವಾಗಿದೆ. ನಮ್ಮ ಉದಾಹರಣೆಯಲ್ಲಿ ರಿಯಾಕ್ಟ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಾಗಿ, ಚಿಂತೆ ಮಾಡಲು ಏನೂ ಇಲ್ಲ, ಏಕೆಂದರೆ ರಿಯಾಕ್ಟ್ ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯವನ್ನು ಔಟ್‌ಪುಟ್ ಫೋಲ್ಡರ್‌ನಂತೆ ಬಳಸುತ್ತದೆ, ಆದರೆ ಕೋನೀಯ ಅಥವಾ ಬೇರೆ ಯಾವುದೋ ಸಂದರ್ಭದಲ್ಲಿ, ಈ ನಿಯತಾಂಕವನ್ನು ಅಗತ್ಯವಿರುವಂತೆ ಬದಲಾಯಿಸಬೇಕಾಗುತ್ತದೆ.

ಈಗ ಇಮೇಜ್ ಸ್ಟ್ರೀಮ್ಸ್ ವಿಭಾಗವನ್ನು ನೋಡೋಣ.

- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-builder  // 1 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-runtime  // 2 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: web-app-builder-runtime // 3
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: nginx-image-runtime // 4
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: 'centos/nginx-112-centos7:latest'

ಮೂರನೇ ಮತ್ತು ನಾಲ್ಕನೇ ಚಿತ್ರಗಳನ್ನು ನೋಡೋಣ. ಅವೆರಡನ್ನೂ ಡಾಕರ್ ಚಿತ್ರಗಳೆಂದು ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ ಮತ್ತು ಅವು ಎಲ್ಲಿಂದ ಬರುತ್ತವೆ ಎಂಬುದನ್ನು ನೀವು ಸ್ಪಷ್ಟವಾಗಿ ನೋಡಬಹುದು.

ಮೂರನೇ ಚಿತ್ರವು ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್ ಆಗಿದೆ ಮತ್ತು ಇದು 8.x ನಲ್ಲಿ ಟ್ಯಾಗ್ ಮಾಡಲಾದ nodeshift/ubi2-s10i-web-app ನಿಂದ ಬಂದಿದೆ ಡಾಕರ್ ಹಬ್.

ನಾಲ್ಕನೆಯದು NGINX ಚಿತ್ರವಾಗಿದೆ (ಆವೃತ್ತಿ 1.12) ಇತ್ತೀಚಿನ ಟ್ಯಾಗ್ ಆನ್ ಆಗಿದೆ ಡಾಕರ್ ಹಬ್.

ಈಗ ಮೊದಲ ಎರಡು ಚಿತ್ರಗಳನ್ನು ನೋಡೋಣ. ಅವೆರಡೂ ಪ್ರಾರಂಭದಲ್ಲಿ ಖಾಲಿಯಾಗಿವೆ ಮತ್ತು ನಿರ್ಮಾಣ ಹಂತದಲ್ಲಿ ಮಾತ್ರ ರಚಿಸಲಾಗಿದೆ. ಮೊದಲ ಚಿತ್ರ, ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್, ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್-ರನ್‌ಟೈಮ್ ಇಮೇಜ್ ಮತ್ತು ನಮ್ಮ ಮೂಲ ಕೋಡ್ ಅನ್ನು ಸಂಯೋಜಿಸುವ ಅಸೆಂಬ್ಲಿ ಹಂತದ ಫಲಿತಾಂಶವಾಗಿದೆ. ಅದಕ್ಕಾಗಿಯೇ ನಾವು ಈ ಚಿತ್ರದ ಹೆಸರಿಗೆ “-ಬಿಲ್ಡರ್” ಅನ್ನು ಸೇರಿಸಿದ್ದೇವೆ.

ಎರಡನೇ ಚಿತ್ರ - react-web-app-runtime - nginx-image-runtime ಮತ್ತು react-web-app-builder ಇಮೇಜ್‌ನಿಂದ ಕೆಲವು ಫೈಲ್‌ಗಳನ್ನು ಸಂಯೋಜಿಸುವ ಫಲಿತಾಂಶವಾಗಿದೆ. ಈ ಚಿತ್ರವನ್ನು ನಿಯೋಜನೆಯ ಸಮಯದಲ್ಲಿ ಸಹ ಬಳಸಲಾಗುತ್ತದೆ ಮತ್ತು ನಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ನ ವೆಬ್ ಸರ್ವರ್ ಮತ್ತು ಸ್ಥಿರ HTML, JavaScript, CSS ಅನ್ನು ಮಾತ್ರ ಒಳಗೊಂಡಿರುತ್ತದೆ.

ಗೊಂದಲ? ಈಗ ಬಿಲ್ಡ್ ಕಾನ್ಫಿಗರೇಶನ್‌ಗಳನ್ನು ನೋಡೋಣ ಮತ್ತು ಅದು ಸ್ವಲ್ಪ ಸ್ಪಷ್ಟವಾಗುತ್ತದೆ.

ನಮ್ಮ ಟೆಂಪ್ಲೇಟ್ ಎರಡು ನಿರ್ಮಾಣ ಸಂರಚನೆಗಳನ್ನು ಹೊಂದಿದೆ. ಇಲ್ಲಿ ಮೊದಲನೆಯದು, ಮತ್ತು ಇದು ಸಾಕಷ್ಟು ಪ್ರಮಾಣಿತವಾಗಿದೆ:

  apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-builder
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-builder:latest // 1
    source:   // 2 
      git:
        uri: ${SOURCE_REPOSITORY_URL}
        ref: ${SOURCE_REPOSITORY_REF}
      contextDir: ${SOURCE_REPOSITORY_DIR}
      type: Git
    strategy:
      sourceStrategy:
        env:
          - name: OUTPUT_DIR // 3 
            value: ${OUTPUT_DIR}
        from:
          kind: ImageStreamTag
          name: web-app-builder-runtime:latest // 4
        incremental: true // 5
      type: Source
    triggers: // 6
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - imageChange: {}
      type: ImageChange

ನೀವು ನೋಡುವಂತೆ, ಲೇಬಲ್ 1 ರೊಂದಿಗಿನ ಸಾಲು ಈ ನಿರ್ಮಾಣದ ಫಲಿತಾಂಶವನ್ನು ನಾವು ಇಮೇಜ್‌ಸ್ಟ್ರೀಮ್ಸ್ ವಿಭಾಗದಲ್ಲಿ ಸ್ವಲ್ಪ ಹಿಂದೆ ನೋಡಿದ ಅದೇ ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್ ಚಿತ್ರದಲ್ಲಿ ಇರಿಸಲಾಗುವುದು ಎಂದು ಹೇಳುತ್ತದೆ.

2 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು ನಿಮಗೆ ಕೋಡ್ ಅನ್ನು ಎಲ್ಲಿಂದ ಪಡೆಯಬೇಕೆಂದು ಹೇಳುತ್ತದೆ. ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ, ಇದು ಜಿಟ್ ರೆಪೊಸಿಟರಿಯಾಗಿದೆ ಮತ್ತು ಸ್ಥಳ, ref ಮತ್ತು ಸಂದರ್ಭ ಫೋಲ್ಡರ್ ಅನ್ನು ನಾವು ಈಗಾಗಲೇ ಮೇಲೆ ನೋಡಿದ ನಿಯತಾಂಕಗಳಿಂದ ನಿರ್ಧರಿಸಲಾಗುತ್ತದೆ.

3 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು ನಾವು ಈಗಾಗಲೇ ನಿಯತಾಂಕಗಳ ವಿಭಾಗದಲ್ಲಿ ನೋಡಿದ್ದೇವೆ. ಇದು OUTPUT_DIR ಪರಿಸರ ವೇರಿಯಬಲ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ, ಇದು ನಮ್ಮ ಉದಾಹರಣೆಯಲ್ಲಿ ಬಿಲ್ಡ್ ಆಗಿದೆ.
ನಾವು ಈಗಾಗಲೇ ಇಮೇಜ್‌ಸ್ಟ್ರೀಮ್ ವಿಭಾಗದಲ್ಲಿ ನೋಡಿದ ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್-ರನ್‌ಟೈಮ್ ಇಮೇಜ್ ಅನ್ನು ಬಳಸಲು 4 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು ಹೇಳುತ್ತದೆ.

S5I ಚಿತ್ರವು ಅದನ್ನು ಬೆಂಬಲಿಸಿದರೆ ಮತ್ತು ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಬಿಲ್ಡರ್ ಚಿತ್ರವು ಬೆಂಬಲಿಸಿದರೆ ನಾವು ಹೆಚ್ಚುತ್ತಿರುವ ನಿರ್ಮಾಣವನ್ನು ಬಳಸಲು ಬಯಸುತ್ತೇವೆ ಎಂದು 2 ನೇ ಸಾಲಿನ ಲೇಬಲ್ ಹೇಳುತ್ತದೆ. ಮೊದಲ ಉಡಾವಣೆಯಲ್ಲಿ, ಅಸೆಂಬ್ಲಿ ಹಂತವು ಪೂರ್ಣಗೊಂಡ ನಂತರ, ಚಿತ್ರವು node_modules ಫೋಲ್ಡರ್ ಅನ್ನು ಆರ್ಕೈವ್ ಫೈಲ್‌ಗೆ ಉಳಿಸುತ್ತದೆ. ನಂತರ, ನಂತರದ ರನ್‌ಗಳಲ್ಲಿ, ನಿರ್ಮಾಣ ಸಮಯವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಚಿತ್ರವು ಈ ಫೋಲ್ಡರ್ ಅನ್ನು ಅನ್ಜಿಪ್ ಮಾಡುತ್ತದೆ.

ಮತ್ತು ಅಂತಿಮವಾಗಿ, 6 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ರೇಖೆಯು ಯಾವುದಾದರೂ ಬದಲಾವಣೆಯಾದಾಗ ಹಸ್ತಚಾಲಿತ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆಯೇ ಬಿಲ್ಡ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ರನ್ ಮಾಡಲು ಕೆಲವು ಪ್ರಚೋದಕಗಳಾಗಿವೆ.

ಒಟ್ಟಾರೆ ಇದು ಸಾಕಷ್ಟು ಪ್ರಮಾಣಿತ ನಿರ್ಮಾಣ ಸಂರಚನೆಯಾಗಿದೆ.

ಈಗ ಎರಡನೇ ನಿರ್ಮಾಣ ಸಂರಚನೆಯನ್ನು ನೋಡೋಣ. ಇದು ಮೊದಲನೆಯದಕ್ಕೆ ಹೋಲುತ್ತದೆ, ಆದರೆ ಒಂದು ಪ್ರಮುಖ ವ್ಯತ್ಯಾಸವಿದೆ.

apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-runtime
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-runtime:latest // 1
    source: // 2
      type: Image
      images:                              
        - from:
            kind: ImageStreamTag
            name: react-web-app-builder:latest // 3
          paths:
            - sourcePath: /opt/app-root/output/.  // 4
              destinationDir: .  // 5
             
    strategy: // 6
      sourceStrategy:
        from:
          kind: ImageStreamTag
          name: nginx-image-runtime:latest
        incremental: true
      type: Source
    triggers:
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - type: ImageChange
      imageChange: {}
    - type: ImageChange
      imageChange:
        from:
          kind: ImageStreamTag
          name: react-web-app-builder:latest // 7

ಆದ್ದರಿಂದ ಎರಡನೇ ಬಿಲ್ಡ್ ಕಾನ್ಫಿಗರೇಶನ್ ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ರನ್‌ಟೈಮ್ ಆಗಿದೆ, ಮತ್ತು ಇದು ಸಾಕಷ್ಟು ಪ್ರಮಾಣಿತವಾಗಿ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ.

1 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು ಹೊಸದೇನಲ್ಲ - ಇದು ಬಿಲ್ಡ್ ಫಲಿತಾಂಶವನ್ನು ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ರನ್‌ಟೈಮ್ ಇಮೇಜ್‌ಗೆ ಹಾಕಲಾಗಿದೆ ಎಂದು ಹೇಳುತ್ತದೆ.

ಹಿಂದಿನ ಕಾನ್ಫಿಗರೇಶನ್‌ನಲ್ಲಿರುವಂತೆ 2 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು, ಮೂಲ ಕೋಡ್ ಅನ್ನು ಎಲ್ಲಿಂದ ಪಡೆಯಬೇಕೆಂದು ಸೂಚಿಸುತ್ತದೆ. ಆದರೆ ಇಲ್ಲಿ ನಾವು ಚಿತ್ರದಿಂದ ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ ಎಂದು ಹೇಳುತ್ತಿರುವುದನ್ನು ಗಮನಿಸಿ. ಇದಲ್ಲದೆ, ನಾವು ಈಗಷ್ಟೇ ರಚಿಸಿದ ಚಿತ್ರದಿಂದ - ರಿಯಾಕ್ಟ್-ವೆಬ್-ಆಪ್-ಬಿಲ್ಡರ್‌ನಿಂದ (3 ನೇ ಸಾಲಿನಲ್ಲಿ ಸೂಚಿಸಲಾಗಿದೆ). ನಾವು ಬಳಸಲು ಬಯಸುವ ಫೈಲ್‌ಗಳು ಚಿತ್ರದ ಒಳಗೆ ಮತ್ತು ಅವುಗಳ ಸ್ಥಳವನ್ನು 4 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲಿನಲ್ಲಿ ಹೊಂದಿಸಲಾಗಿದೆ, ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ ಅದು /opt/app-root/output/ ಆಗಿದೆ. ನಿಮಗೆ ನೆನಪಿದ್ದರೆ, ನಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನಿರ್ಮಿಸುವ ಫಲಿತಾಂಶಗಳ ಆಧಾರದ ಮೇಲೆ ರಚಿಸಲಾದ ಫೈಲ್‌ಗಳನ್ನು ಇಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ.

ಲೇಬಲ್ 5 ನೊಂದಿಗೆ ಪದದಲ್ಲಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ಗಮ್ಯಸ್ಥಾನ ಫೋಲ್ಡರ್ ಪ್ರಸ್ತುತ ಡೈರೆಕ್ಟರಿಯಾಗಿದೆ (ಇದೆಲ್ಲವೂ, ನೆನಪಿಡಿ, ಓಪನ್‌ಶಿಫ್ಟ್ ಎಂಬ ಕೆಲವು ಮಾಂತ್ರಿಕ ವಿಷಯದೊಳಗೆ ಚಾಲನೆಯಲ್ಲಿದೆ ಮತ್ತು ನಿಮ್ಮ ಸ್ಥಳೀಯ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿ ಅಲ್ಲ).

ತಂತ್ರ ವಿಭಾಗ - 6 ಲೇಬಲ್ ಮಾಡಿದ ಸಾಲು - ಮೊದಲ ನಿರ್ಮಾಣ ಸಂರಚನೆಯನ್ನು ಹೋಲುತ್ತದೆ. ಈ ಸಮಯದಲ್ಲಿ ಮಾತ್ರ ನಾವು nginx-image-runtime ಅನ್ನು ಬಳಸಲಿದ್ದೇವೆ, ಅದನ್ನು ನಾವು ಈಗಾಗಲೇ ಇಮೇಜ್ಸ್ಟ್ರೀಮ್ ವಿಭಾಗದಲ್ಲಿ ನೋಡಿದ್ದೇವೆ.

ಅಂತಿಮವಾಗಿ, 7 ಎಂದು ಲೇಬಲ್ ಮಾಡಲಾದ ಸಾಲು ಟ್ರಿಗ್ಗರ್‌ಗಳ ವಿಭಾಗವಾಗಿದ್ದು, ಪ್ರತಿ ಬಾರಿ ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ಬಿಲ್ಡರ್ ಇಮೇಜ್ ಬದಲಾದಾಗ ಈ ಬಿಲ್ಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.

ಇಲ್ಲದಿದ್ದರೆ, ಈ ಟೆಂಪ್ಲೇಟ್ ಸಾಕಷ್ಟು ಪ್ರಮಾಣಿತ ನಿಯೋಜನೆ ಕಾನ್ಫಿಗರೇಶನ್ ಮತ್ತು ಸೇವೆಗಳು ಮತ್ತು ಮಾರ್ಗಗಳಿಗೆ ಸಂಬಂಧಿಸಿದ ವಿಷಯಗಳನ್ನು ಒಳಗೊಂಡಿದೆ, ಆದರೆ ನಾವು ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗೆ ಹೋಗುವುದಿಲ್ಲ. ನಿಯೋಜಿಸಲಾಗುವ ಚಿತ್ರವು ರಿಯಾಕ್ಟ್-ವೆಬ್-ಅಪ್ಲಿಕೇಶನ್-ರನ್‌ಟೈಮ್ ಚಿತ್ರವಾಗಿದೆ ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ.

ಅಪ್ಲಿಕೇಶನ್ ನಿಯೋಜನೆ

ಈಗ ನಾವು ಟೆಂಪ್ಲೇಟ್ ಅನ್ನು ನೋಡಿದ್ದೇವೆ, ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನಿಯೋಜಿಸಲು ಅದನ್ನು ಹೇಗೆ ಬಳಸುವುದು ಎಂದು ನೋಡೋಣ.

ನಮ್ಮ ಟೆಂಪ್ಲೇಟ್ ಅನ್ನು ನಿಯೋಜಿಸಲು ನಾವು oc ಎಂಬ OpenShift ಕ್ಲೈಂಟ್ ಟೂಲ್ ಅನ್ನು ಬಳಸಬಹುದು:

$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f

$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app

ಮೇಲಿನ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ನಲ್ಲಿನ ಮೊದಲ ಆಜ್ಞೆಯು ಟೆಂಪ್ಲೇಟ್ ಅನ್ನು ಹುಡುಕಲು ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿ ಎಂಜಿನಿಯರಿಂಗ್ ಮಾರ್ಗವಾಗಿದೆ./openshiftio/application.yaml.

ಎರಡನೆಯ ಆಜ್ಞೆಯು ಈ ಟೆಂಪ್ಲೇಟ್ ಅನ್ನು ಆಧರಿಸಿ ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸರಳವಾಗಿ ರಚಿಸುತ್ತದೆ.

ಈ ಆಜ್ಞೆಗಳು ಕೆಲಸ ಮಾಡಿದ ನಂತರ, ನಾವು ಎರಡು ಅಸೆಂಬ್ಲಿಗಳನ್ನು ಹೊಂದಿದ್ದೇವೆ ಎಂದು ನಾವು ನೋಡುತ್ತೇವೆ:

ಓಪನ್‌ಶಿಫ್ಟ್‌ನಲ್ಲಿನ ಆಧುನಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಭಾಗ 2: ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳು

ಮತ್ತು ಅವಲೋಕನ ಪರದೆಗೆ ಹಿಂತಿರುಗಿ, ನಾವು ಪ್ರಾರಂಭಿಸಲಾದ ಪಾಡ್ ಅನ್ನು ನೋಡುತ್ತೇವೆ:

ಓಪನ್‌ಶಿಫ್ಟ್‌ನಲ್ಲಿನ ಆಧುನಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಭಾಗ 2: ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳು

ಲಿಂಕ್ ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ನಮ್ಮನ್ನು ನಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಕರೆದೊಯ್ಯಲಾಗುತ್ತದೆ, ಇದು ಡೀಫಾಲ್ಟ್ ರಿಯಾಕ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ ಪುಟವಾಗಿದೆ:

ಓಪನ್‌ಶಿಫ್ಟ್‌ನಲ್ಲಿನ ಆಧುನಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಭಾಗ 2: ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳು

ಪೂರಕ 1

ಕೋನೀಯ ಪ್ರೇಮಿಗಳಿಗಾಗಿ ನಾವು ಸಹ ಹೊಂದಿದ್ದೇವೆ ಉದಾಹರಣೆ ಅಪ್ಲಿಕೇಶನ್.

OUTPUT_DIR ವೇರಿಯೇಬಲ್ ಹೊರತುಪಡಿಸಿ, ಇಲ್ಲಿರುವ ಮಾದರಿಯು ಒಂದೇ ಆಗಿರುತ್ತದೆ.

ಪೂರಕ 2

ಈ ಲೇಖನದಲ್ಲಿ ನಾವು NGINX ಅನ್ನು ವೆಬ್ ಸರ್ವರ್ ಆಗಿ ಬಳಸಿದ್ದೇವೆ, ಆದರೆ ಅದನ್ನು Apache ನೊಂದಿಗೆ ಬದಲಾಯಿಸುವುದು ತುಂಬಾ ಸುಲಭ, ಫೈಲ್‌ನಲ್ಲಿನ ಟೆಂಪ್ಲೇಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿ NGINX ಚಿತ್ರ ಮೇಲೆ ಅಪಾಚೆ ಚಿತ್ರ.

ತೀರ್ಮಾನಕ್ಕೆ

ಈ ಸರಣಿಯ ಮೊದಲ ಭಾಗದಲ್ಲಿ, ಓಪನ್‌ಶಿಫ್ಟ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ಆಧುನಿಕ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ತ್ವರಿತವಾಗಿ ನಿಯೋಜಿಸುವುದು ಹೇಗೆ ಎಂದು ನಾವು ತೋರಿಸಿದ್ದೇವೆ. ಇಂದು ನಾವು ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಚಿತ್ರವು ಏನು ಮಾಡುತ್ತದೆ ಮತ್ತು ಹೆಚ್ಚು ಉತ್ಪಾದನೆ-ಸಿದ್ಧ ಅಪ್ಲಿಕೇಶನ್ ನಿರ್ಮಾಣವನ್ನು ರಚಿಸಲು ಚೈನ್ಡ್ ಬಿಲ್ಡ್‌ಗಳನ್ನು ಬಳಸಿಕೊಂಡು NGINX ನಂತಹ ಶುದ್ಧ ವೆಬ್ ಸರ್ವರ್‌ನೊಂದಿಗೆ ಹೇಗೆ ಸಂಯೋಜಿಸಬಹುದು ಎಂಬುದನ್ನು ನಾವು ನೋಡಿದ್ದೇವೆ. ಈ ಸರಣಿಯ ಮುಂದಿನ ಮತ್ತು ಅಂತಿಮ ಲೇಖನದಲ್ಲಿ, OpenShift ನಲ್ಲಿ ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ಗಾಗಿ ಡೆವಲಪ್‌ಮೆಂಟ್ ಸರ್ವರ್ ಅನ್ನು ಹೇಗೆ ರನ್ ಮಾಡುವುದು ಮತ್ತು ಸ್ಥಳೀಯ ಮತ್ತು ರಿಮೋಟ್ ಫೈಲ್‌ಗಳ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಅನ್ನು ಖಚಿತಪಡಿಸುವುದು ಹೇಗೆ ಎಂದು ನಾವು ತೋರಿಸುತ್ತೇವೆ.

ಈ ಲೇಖನಗಳ ಸರಣಿಯ ವಿಷಯಗಳು

  • 1 ಭಾಗ: ಕೆಲವೇ ಹಂತಗಳಲ್ಲಿ ಆಧುನಿಕ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹೇಗೆ ನಿಯೋಜಿಸುವುದು;
  • ಭಾಗ 2: ಉತ್ಪಾದನಾ ನಿಯೋಜನೆಗಾಗಿ ಸಂಬಂಧಿತ OpenShift ಅಸೆಂಬ್ಲಿಗಳನ್ನು ಬಳಸಿಕೊಂಡು NGINX ನಂತಹ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ HTTP ಸರ್ವರ್ ಇಮೇಜ್‌ನೊಂದಿಗೆ ಹೊಸ S2I ಚಿತ್ರವನ್ನು ಹೇಗೆ ಬಳಸುವುದು;
  • ಭಾಗ 3: OpenShift ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ಗಾಗಿ ಡೆವಲಪ್‌ಮೆಂಟ್ ಸರ್ವರ್ ಅನ್ನು ರನ್ ಮಾಡುವುದು ಮತ್ತು ಅದನ್ನು ಸ್ಥಳೀಯ ಫೈಲ್ ಸಿಸ್ಟಮ್‌ನೊಂದಿಗೆ ಸಿಂಕ್ರೊನೈಸ್ ಮಾಡುವುದು ಹೇಗೆ.

ಹೆಚ್ಚುವರಿ ಸಂಪನ್ಮೂಲಗಳು

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ