Thanatcha Kromsang
2 min readApr 12, 2018

มาจับ React ยัดใส่ Container กันเถอะ! (React+Docker)

เคยเป็นกันรึเปล่า? รันโค้ดในเครื่องตัวเองผ่านแต่ทำไมรันเครื่องคนอื่นแล้วพังไม่เป็นท่าเลย วันนี้เราจะมาแก้ปัญหานั้นสำหรับการ Deploy react website กันโดยใช้ docker และ react

Docker คืออะไร?

Docker คือเทคโนโลยีที่ช่วยการ Development และการ Deployment ให้ง่ายขึ้นและไวขึ้น โดยเฉพาะถ้าเราทำงานกับ Microservices โดย Docker นั้นจะนำมาใช้ในการเชื่อมระหว่างแต่ละ Services ภายในโครงสร้างระบบของเรานั่นเอง และข้อดีอีกข้อที่สำคัญคือ การกำจัดปัญหาที่เกิดขึ้นจาก OS, หรือ Environment ที่เราทำงานอยู่ทำให้ไม่ว่าจะนำ Project นี้ไปทำงานที่ไหนก็ทำงานได้ โม้มามากแล้ว มาลองใช้จริงกันเลยจะดีกว่า!

ตัวอย่างนี้จะนำเสนอวิธีการนำ Create React App มาใช้งานกับ Docker

โดยสิ่งที่ต้องมีก็ได้แก่

  • Node v9.+
  • Docker CE v18.+
  • Create React App v1.5.+
  • Docker Compose

Project Setup

ทำการติดตั้ง create-react-app:

$ npm install -g create-react-app

ทำการติดตั้ง Docker ขั้นตอนของแต่ละ OS แตกต่างกันแนะนำให้ติดตั้งโดยศึกษาขั้นตอนผ่านลิงค์ข้างล่าง

หลังจากที่ติดตั้งทุกอย่างสำเร็จแล้วก็จะทำการ generate project ขึ้นมา

$ create-react-app application
$ cd application

create-react-app จะทำการ generate โปรเจคที่ชื่อ application ขึ้นมา

หลังจากนั้นทำการสร้าง Dockerfile เพื่อใช้เป็น Instruction ในการสร้าง Container

# base image
FROM node:9.11

# set working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app

# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts -g

# start app
CMD ["npm", "start"]

Dockerfile ข้างต้นนั้นจะทำงานตามลำดับ

  • ดึงข้อมูลจาก base image ของ node และนำไปใช้กับคำสั่งต่อๆไป
  • สร้าง directory และ set directory เป็น base directory สำหรับใช้งานคำสั่ง RUN, COPY, CMD
  • เพิ่ม node_modules เข้าไปใน environment path
  • copy package.json ที่อยู่ใน directory ปัจจุบันไปไว้ใน container
  • npm install เพื่อลง dependencies
  • ทำการติดตั้ง react-scripts เพื่อใช้ในการเรียกใช้งานคำสั่งภายใน package.json
  • npm start เพื่อเรียกใช้งาน react-scripts start

อ่านเพิ่มเติมเกี่ยวกับ Dockerfile

หลังจากนั้นทำการสร้าง .dockerignore เพื่อทำให้ build process รวดเร็วขึ้นเพราะ dependencies จะไม่ถูกส่งเข้าไปใน container

node_modules

เริ่มทำการ build image จาก dockerfile ภายใน directory ปัจจุบัน

$ docker build -t docker-react .

จะได้ images ชื่อ docker-react หลังจากนั้นก็ทำการเรียกใช้งาน container ผ่าน terminal ด้วยคำสั่ง

$ docker run -it \
-v ${PWD}:/usr/src/app \
-v /usr/src/app/node_modules \
-p 3000:3000 \
--rm \
docker-react

ผลลัพธ์ที่ได้จะอยู่บน localhost:3000 แต่เราก็ต้องเปิด process ที่ใช้เรียก container ค้างไว้ ทีนี้ถ้าเราไม่อยากเปิด process ค้างไว้แล้วสั่งให้มันทำงานอยู่เบื้องหลังแทนล่ะ? ก็เพิ่มคำสั่ง detach เข้าไป

$ docker run -it \
-v ${PWD}:/usr/src/app \
-v /usr/src/app/node_modules \
-p 3000:3000 \
--rm \
-d \
docker-react

จะสังเกตว่าถึงแม้เราจะย้าย development server เรามาไว้บน container เรียบร้อยแล้วแต่ก็ยังต้องผ่านกระบวนการมากมายกว่าจะได้ใช้งานและในกรณีที่ต้องทำ multi-container ตัวอย่างเช่น react production server ภายใต้ nginx ก็ทำให้ยุ่งยากอยู่ดี จึงขอนำ docker compose มาช่วยในการจัดการเรื่อง multi-container

การใช้งาน docker-compose ทำได้โดยการเพิ่ม docker-compose.yml ไว้ใน base directory

version: '3.5'services:sample-app:
container_name: react-docker
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/usr/src/app'
- '/usr/src/app/node_modules'
ports:
- '3000:3000'
environment:
- NODE_ENV=${NODE_ENV}

และสร้าง .env ไว้สำหรับเรียกใช้ environment variables

#!/usr/bin/env bash# Node
NODE_ENV=development

หลังจากนั้นก็เรียกใช้งานคำสั่ง

$ docker-compose up -d --build

จบขั้นตอนการใช้งานสร้าง container โดยใช้ docker-compose ทีนี้ลูกเล่นเพิ่มเติมของ docker-compose ก็คือการเขียน multi-container สำหรับเรียกใช้งานหลายๆ application พร้อมๆกันโดยสามารถศึกษาเพิ่มเติมการเขียน docker-compose.yml จาก

อ่านเพิ่มเติมเกี่ยวกับ Docker Compose

วันนี้ก็ขอจบการสร้าง react container โดยใช้ docker เพียงเท่านี้

Happy coding ❤

Thanatcha Kromsang

Software Engineer | Vim Enthusiast | Linux Lover | Neccessary DevOps | Full-stack Developer | ❤ Graphql