Quá chán với việc cài lại máy mỗi khi bắt đầu dự án mới nên BichPhuong quyết định tự setup docker dành riêng để làm việc với Laravel - Vol 1

Mở bài

Thật ra bài viết này chẳng liên quan gì đến cô vợ quốc dân Bích Phương lắm nhưng vì sự nghiệp làm lều báo nên đành lôi cô vào để giật tít câu view 😌

Chắc hẳn với những bạn đã và đang làm lập trình viên hoặc học nghề lập trình đều đã từng phải điên đầu mỗi khi bắt tay vào cài đặt môi trường máy để chạy một dự án nào đó. Ngay cả mình cũng vậy, với mỗi project lại đòi hỏi một cấu hình môi trường và các gói tin đi kèm khác nhau khiến việc mỗi lần setup môi trường cho dự án mới là một công việc cực kỳ khổ dâm.

Nói đơn giản như bạn đang là một dev Laravel vui tính thì bỗng một ngày sếp đến vỗ vai và bảo: "mai code ruby nhé cưng". Thế là bạn điên cuồng lên youtube search: Cấu hình máy Ruby cho người mới bắt đầu! Nhưng khi pull code về thì lỗi lên lỗi xuống do thiếu cái này hoặc hỏng cái kia. Rồi một ngày đẹp trời nữa cũng chẳng hiểu vì lý do gì mà bạn pull code của đồng nghiệp về nhưng không chạy được, mặc dù trên máy đồng nghiệp chạy ngon. Vân vân các trường hợp éo le khác cũng tương tự vậy, xuất phát chính từ việc môi trường dev thiếu sự đồng bộ giữa các dev với nhau.

Lúc này giải pháp chắc ngoài việc tiếp tục khổ dâm ra thì chỉ còn sử dụng Docker mà thôi. Còn cơ bản về Docker thì bạn có thể tìm đọc các bài viết khác trên Viblo, tôi xin phép không đề cập đến. Bài viết dưới đây của tôi chỉ là chia sẻ cách tôi tự cấu hình một Docker Image để sử dụng, có nhiều bạn

À nhân tiện thì bài này khá dài nên tôi xin phép chia 2 phần. Bài cũng có tham khảo từ nhiều nguồn khác nhau, lấy chỗ này đập chỗ kia, lỗi chỗ này copy chỗ kia vào sửa, cộng thêm cả sự đau khổ và đoán mò nên xin phép để lại credit trong phần 2 🤧

1. Cài đặt Laravel và các package đi kèm

Việc này nhằm mục đích tiết kiệm thời gian cài đặt Laravel cho các bạn. Nếu các bạn đã từng sử dụng Docker sẽ thấy rằng các Image sẽ chỉ là môi trường để chạy chứ không hề có Laravel đi kèm. Và đương nhiên ở đây mình setup một image chỉ để chạy Laravel nên mình sẽ muốn khi Image đó được build thì nó sẽ đồng thời tự init cả Project Laravel cho mình luôn.

Còn việc cài trước Laravel này chỉ là để bạn lấy được file composer.json chứa các dependencies của Laravel mà thôi.

Mình sẽ tạo một thư mục tên docker-laravel và clone Laravel phiên bản mới nhất từ Github về, còn bạn nào không thích thì có thể cài trực tiếp qua Laravel CLI cũng được

$ git clone https://github.com/laravel/laravel.git docker-laravel

Đợi quá trình cài đặt kết thúc thì bạn di chuyển vào thư mục docker-laravel

$ cd ~/docker-laravel

Tiếp theo nếu ai đang có nhu cầu cài đặt Composer luôn thì có thể tham khảo, còn mình thì sẽ bỏ qua.

Trước đây bạn hay cài đặt các package của Laravel bằng cách chạy composer install. Nhưng việc này tốn thời gian và tài nguyên máy, thay vào đó bạn có thể sử dụng một Image Docker tên Composer để cài đặt các package này nhanh hơn và tốn ít tài nguyên máy hơn:

$ docker run --rm -v $(pwd):/app composer install

Bằng việc sử dụng các flags --rm-v sẽ cho phép container được khởi tạo -> cài đặt các Composer vào vendor -> mount ngược lại vào thư mục Laravel của các bạn sau đó xóa đi ngay lập tức. Rất nhanh và gọn, nhưng vì mình chỉ cần cái file composer.json thôi nên mình sẽ bỏ qua bước này, nói cho biết thôi.

Cuối cùng bạn phân quyền lại cho thư mục vừa tạo:

$ sudo chown -R $USER:$USER ~/docker-laravel

Flash back

Các bạn biết rằng để có thể chạy được một project Laravel thì chúng ta sẽ cần tối thiểu 2 thứ:

  • Môi trường PHP
  • Webserver

Vậy nên khi đi cài đặt Docker Laravel chúng ta cũng sẽ cần tối thiểu 2 Image như vậy. Cần môi trường PHP để chạy được Laravel và cần Webserver để có thể expose nó thành một trang web. Ở trong tutorial này mình cũng sẽ làm như vậy nhưng sẽ bonus thêm cả việc cài đặt luôn database nữa cho nó mát. Vậy là công việc tiếp theo chúng ta sẽ cần cài đặt 3 image: PHP, Webserver, Database ( Ở đây mình sẽ cài MySQL)

Và để có thể cài đặt nhiều service cùng một lúc, chắc chắn chúng ta không thể nào không dùng Docker Compose. Với Docker Compose File mà chúng ta sắp tạo sẽ có 2 lựa chọn cho bạn:

  1. Pull thẳng một Image sẵn có từ Docker Hub về dùng khỏi mất công suy nghĩ
  2. Tự viết một Dockerfile để tạo một Container với đầy đủ những thứ mà chúng ta cần

Đương nhiên là mình sẽ chọn cách số 2 vì đa số các Image sẵn có đều chỉ xây dựng môi trường chứ không kéo luôn Laravel về xài, mà mình lại đang muốn ánh xạ luôn cả cái Laravel để khi mình chạy Docker Compose lên, mình sẽ đồng thời cài đặt luôn Laravel vào đó, cho nó mát.

2. Viết Dockerfile

Nói thật đây cũng là công đoạn khiến mình đau khổ nhiều nhất, lỗi lên lỗi xuống nhưng cuối cùng nhờ một sự chắp vá kỳ diệu mà mình đã có thể khởi tạo thành công một Container từ cái Dockerfile này, tất cả những gì mình viết ở đây đều chưa được tối ưu hay tối giản, mà chỉ dừng lại ở mức chạy được nên nếu các bạn có muốn đóng góp cho cái Container này nhẹ bớt thì mình xin welcome =))

Đầu tiên chúng ta tạo một Dockerfile trong thư mục docker-laravel

$ nano ~/docker-laravel/Dockerfile

Chiếc Dockerfile này sẽ được khởi tạo dựa trên một Image có sẵn, và cài đặt thêm các package phù hợp với môi trường mà các bạn cần thiết để chạy được Laravel, phần code sẽ như sau:

FROM php:7.4-fpm

# Thư mục sẽ ánh xạ toàn bộ code trong Laravel trên máy local vào Container 
WORKDIR /var/www

# Cài đặt các dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
  autoconf \
  build-essential \
  apt-utils \
  zlib1g-dev \
  libzip-dev \
  unzip \
  zip \
  libmagick++-dev \
  libmagickwand-dev \
  libpq-dev \
  libfreetype6-dev \
  libjpeg62-turbo-dev \
  libpng-dev \
  libwebp-dev \ 
  libxpm-dev 

# Cài đặt composer - để lát còn cài Laravel
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Cài đặt các phần mềm cho PHP
RUN docker-php-ext-configure gd --with-freetype --with-jpeg

RUN docker-php-ext-install gd intl pdo_mysql pdo_pgsql mysqli zip

RUN pecl install imagick-3.4.3

RUN pecl install xdebug && docker-php-ext-enable xdebug

RUN docker-php-ext-enable imagick

# Tạo các quyền user 
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy toàn bộ code trong thư mục trên máy vào thư mục ánh xạ trong Container
COPY . /var/www

# Copy quyền trên thư mục máy vào thư mục ánh xạ 
COPY --chown=www:www . /var/www

USER www

# Mở cổng 9000 và chạy command khởi động php-fpm server 
EXPOSE 9000
CMD ["php-fpm"]

Giải thích một chút, đầu tiên Dockerfile sẽ tạo một Container dựa trên Image đã có sẵn ở Docker Hub là php:7.4-fpm. Đây là một Image đã được cài sẵn PHP nhưng chưa có các package đi kèm, nên công việc của chúng ta là cài đặt thêm các gói package đi kèm để phù hợp với một môi trường chạy Laravel, công đoạn này ở trong Dockerfile các bạn có thể thấy qua từ khóa RUN.

Để giảm thiểu các lỗ hổng bảo mật khi chạy Container, chúng ta cũng đồng thời tạo ra một group user tên www được cấp quyền đọc và ghi trên /var/www folder thay vì sử dụng mặc định chạy Container dưới quyền root.

Cuối cùng, từ khóa EXPOSECMD cho phép mở cổng 9000 và khởi chạy PHP trên Container để sau này khi thiết lập kết nối mạng, ta có thể kết nối Container PHP với Container chứa Webserver.

Tạm kết vol 1

Đến đây thì bạn đã có thể thử khởi chạy một Container với Dockerfile như ở trên, các thông số trong Container bạn có thể tùy biến bằng cách thay đổi các thông số trong Dockerfile.

Trong phần sau mình sẽ tiếp tục viết Docker Compose file và cấu hình các Service để liên kết các Container lại với nhau. Cám ơn các bạn đã theo dõi bài viết

References:


All Rights Reserved