Magento 2 Docker environment
Bài đăng này đã không được cập nhật trong 4 năm
Với một nền tảng tương đối lớn như Magento, việc cài đặt để nó chạy thôi cũng khá mất công, vì kiến trúc của nó yêu cầu khá nhiều các thành phần, config liên quan. Vì vậy, với một team phát triển thì việc sử dụng docker trong trường hợp này có thể nói khá là "perfect choice", kiểu như "one click install" vậy : D Chỉ mất thời gian config docker lúc ban đầu, sau đó mọi người trong team hay kể cả member mới sau này có thể dễ dàng dựng môi trường phát triển, cũng như đảm bảo môi trường dev giữa các thành viên không quá khác biệt, tránh phát sinh các bug không đáng có liên quan đến "máy của em".
Trong bài viết này, chúng ta sẽ tìm hiểu về công việc config docker lúc ban đầu nó như thế nào : D
Get Magento 2 source code
Có 2 cách để lấy về source code của Magento 2, ở đây là Magento Commerce version đó là:
-
Download file zip từ trang www.magento.com, lưu ý là bạn phải có tài khoản để download bản Commerce (bản dành cho doanh nghiệp, mất phí), sau đó unzip vào thư mục:
unzip -d magento-ee Magento-EE-2.3.4-2020-01-22-11-32-19.zip
-
Sử dụng
composer
để tạo project:composer create-project --repository-url=https://repo.magento.com/ magento/project-enterprise-edition magento-ee
Khi chạy command, nó sẽ yêu cầu bạn nhập username và password để có thể download bản Commerce, tham khảo hướng dẫn lấy authentication keys.
Sau đấy, bạn có thể lưu các keys này vào file
auth.json
để mỗi khi dùngcomposer update
haycomposer require
bạn không phải nhập lại nữa, đã có file mẫuauth.json.sample
:cd magento-ee cp auth.json.sample auth.json
Tất nhiên bạn cũng nên cho file
auth.json
vào file.gitignore
để tránh commit file này lên remote repository.
Sau khi đã lấy được source code, việc đầu tiên nên làm đó là add luôn vào git để quản lý và theo dõi các thay đổi:
cd magento-ee
git init
git add .
git commit -m 'Init magento commerce 2.3.4'
Vì trong source code lấy về đã có sẵn file .gitignore
nên bạn không phải lo git add cả những file thừa.
System requirements
Về hệ điều hành, tất nhiên đó là Linux (chẳng hạn các distro như RedHat Enterprise Linux (RHEL), CentOS, Ubuntu, Debian,...) và theo docs của Magento là họ không đảm bảo việc chạy Magento trên các hệ điều hành Windows hay MacOS. Hệ điều hành nên được cài sẵn các tools:
bash
gzip
lsof
mysql
mysqldump
nice
php
sed
tar
Về bộ nhớ RAM, Magento khuyên dùng đó là > 2GB, sở dĩ nó cần nhiều bộ nhớ như vậy chủ yếu là do quá trình upgrade Magento hay extensions, còn riêng về PHP memory limit chỉ cần < 1GB là đủ để chạy website rồi.
Web servers có thể là Apache hoặc Nginx. Magento recommend sử dụng Nginx và PHP-FPM để được hiệu năng tốt hơn, vì thế ở đây chúng ta cũng sẽ dùng Nginx.
Database sẽ là MySQL 5.7.
PHP version 7.2 hoặc 7.3 (recommend) và các extensions:
ext-bcmath
ext-ctype
ext-curl
ext-dom
ext-gd
ext-hash
ext-iconv
ext-intl
ext-mbstring
ext-openssl
ext-pdo_mysql
ext-simplexml
ext-soap
ext-xsl
ext-zip
ext-sockets
lib-libxml
PHP OPcache nên được enable và các PHP settings:
- Timezone: https://www.php.net/manual/en/timezones.php
- PHP memory limit: khi chạy ở môi trường production có thể để limit là 1GB, còn ở môi trường dev cần phải upgrade magento hay extensions hoặc chạy unit test thì có thể để là 2 - 3GB.
- Thiết lập
opcache.save_comments
do Magento 2 sử dụng PHP code comments để generate code.
date.timezone = Asia/Ho_Chi_Minh
memory_limit = 2G
opcache.save_comments = 1
Magento 2 sử dụng nhiều đến cookie, do đó ở môi trường dev cũng nên sử dụng domain để support cookie tốt hơn so với localhost hay 127.0.0.1. Ngoài ra HTTPS cũng là yêu cầu thiết yếu khi go live, do đó chúng ta cũng setup HTTPS cho môi trường dev luôn.
Mail server cũng cần thiết khi dev, ở đây chúng ta sẽ sử dụng Mailhog để tạo SMTP server dev.
Redis cũng recommend được sử dụng cho page caching và sessions, để đảm bảo khả năng scale hay dùng load balancer, recommend Redis 5.0.
Tương tự Varnish cũng không thể thiếu khi go live, do đó chúng ta cũng thiết lập để chạy Varnish 6.2.
Xây dựng docker environment
Về cơ bản chúng ta xây dựng các docker containers như sau:
Sử dụng docker-compose
, mỗi container được mô tả bằng một service
:
version: '3'
services:
php:
#...
nginx:
#...
mysql:
#...
redis:
#...
mail-server:
#...
varnish:
#...
PHP FPM
Đầu tiên là container cho PHP-FPM. Do yêu cầu cần nhiều extensions, nên sẽ không có image có sẵn nên chúng ta sẽ tạo mới image bằng Dockerfile. Image nổi bật thường dùng cho PHP-FPM đó là php:7.3-fpm
. Trong quá trình tạo Dockerfile, chúng ta có thể sử dụng image để tạo container và chạy thử cách lệnh trực tiếp cài đặt trực tiếp:
docker run -it --name php73fpm php:7.3-fpm bash
Ngoài việc cài các PHP extensions, chúng ta sẽ cài thêm một số công cụ vì đây là container thường được sử dụng để tương tác với Magento thông qua lệnh php bin/magento
như git
, vim
, cron
để chạy Magento cron hay composer
(cần thêm unzip
)...
FROM php:7.3-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libicu-dev \
libxml2-dev \
libxslt-dev \
libzip-dev \
git vim unzip cron \
--no-install-recommends \
&& rm -r /var/lib/apt/lists/*
RUN docker-php-ext-configure gd --with-jpeg-dir=/usr/lib \
--with-freetype-dir=/usr/include/freetype2 \
&& docker-php-ext-install -j$(nproc) gd
RUN docker-php-ext-configure intl \
&& docker-php-ext-install -j$(nproc) intl
RUN docker-php-ext-install -j$(nproc) opcache bcmath pdo_mysql soap xsl zip sockets
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php \
&& mv composer.phar /usr/local/bin/composer
# Create user magento
RUN useradd -m -s /bin/bash magento \
&& usermod -a -G www-data magento
RUN cp "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
ADD ./php-custom.ini $PHP_INI_DIR/conf.d/
CMD ["php-fpm"]
EXPOSE 9000
Chú thích các package:
libfreetype6-dev
,libjpeg62-turbo-dev
,libpng-dev
cần dùng để cài extensiongd
.libicu-dev
cần dùng cho extensionintl
libxml2-dev
dùng cho extensionsoap
libxslt-dev
dùng cho extensionxsl
- Và
libzip-dev
dùng cho extensionzip
Sau khi cài xong các package trong hệ thống, chúng ta xóa cache của apt-get
để giảm kích thước của image.
Một user mới là magento
được tạo trong hệ thống, user này là user để chúng ta thực hiện lệnh php bin/magento
nhằm đảm bảo file permissions không bị conflict giữa web server user wwww-data
và cli user magento
, bằng cách thêm user magento
vào group www-data
, sau đó thiết lập quyền ghi cho group www-data
. Chi tiết, bạn có thể tham khảo thêm https://devdocs.magento.com/guides/v2.3/install-gde/prereq/file-system-perms.html#perms-private
Bạn có tìm hiểu thêm về bit
s
haysetgid
trong chmod, cụ thể ở đây command:
find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} +
Mục đích của Magento là muốn các file hay folder được tạo mới trong các thư mục
var
,generated
,vendor
,pub/static
pub/media
vàapp/etc
sẽ luôn thuộc group của folder cha, cho dù user tạo file hay folder đó có thuộc group gì đi chăng nữa. Ở đây là group của user chạy web serverwww-data
ở bước chạy lệnhchown -R :www-data .
haychgrp -R www-data .
Sau đó là tạo file php.ini
mặc định từ file example php.ini-development
và add một số setting khác bằng file php-custom.ini
:
date.timezone=Asia/Ho_Chi_Minh
opcache.save_comments = 1
; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 2G
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 50M
; Sets max size of post data allowed.
; http://php.net/post-max-size
post_max_size = 60M
max_execution_time = 18000
Mặc định, container chạy ở cổng 9000, do đó các container khác, cụ thể là nginx có thể kết nối vào địa chỉ: php:9000
.
Ta có docker-compose service đầu tiên:
version: "3"
services:
php:
build:
context: ./dev/docker/images/php
restart: always
working_dir: /var/www/html/magento
volumes:
- ./:/var/www/html/magento
expose:
- "9000"
Nginx
Tiếp theo là container cho web server Nginx, có nhiệm vụ giao tiếp với PHP-FPM và trả về response cho client. Với service này, để tận dụng khả năng dùng lại các image có sẵn và giảm bớt việc phải build image, nên chúng ta không cần sử dụng custom Dockerfile, ở đây chỉ cần sử dụng image nginx
và thực hiện mount file config:
services:
php:
#...
nginx:
restart: always
image: nginx:latest
working_dir: /var/www/html/magento
volumes:
- ./:/var/www/html/magento
- ./dev/docker/images/nginx/magento.conf:/etc/nginx/conf.d/default.conf
expose:
- "80"
File magento.conf
chỉ ngắn gọn như thế này vì Magento đã cung cấp sẵn 1 file sample:
upstream fastcgi_backend {
server php:9000;
}
server {
listen 80;
server_name _;
set $MAGE_ROOT /var/www/html/magento;
set $MAGE_DEBUG_SHOW_ARGS 1;
include /var/www/html/magento/nginx.conf.sample;
}
Lưu ý đến đường dẫn /var/www/html/magento
. Và trong file nginx.conf.sample
có một đoạn set document root:
root $MAGE_ROOT/pub;
MySQL
Tương tự, chúng ta cũng có thể dùng image mysql
trực tiếp và tạo user, db qua init SQL file mà không cần custom image:
services:
php:
#...
nginx:
#...
mysql:
restart: always
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./dev/docker/images/mysql/initdb:/docker-entrypoint-initdb.d
- ./dev/docker/data/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
expose:
- "3306"
File init SQL: tạo database user và database dùng cho Magento
# Create Databases
CREATE DATABASE IF NOT EXISTS `magento_db`;
# Create user and grant rights
FLUSH PRIVILEGES;
CREATE USER 'magento'@'%' IDENTIFIED BY 'secret';
GRANT ALL ON magento_db.* TO 'magento'@'%';
Bạn có thể publish port 3306
để kết nối với MySQL ở host machine (bằng MySQL Workbench, Phpmyadmin,...) hoặc dùng container adminer:
services:
php:
#...
nginx:
#...
mysql:
#
adminer:
restart: always
image: adminer
volumes:
- ./dev/docker/images/adminer/php-custom.ini:/usr/local/etc/php/conf.d/php-custom.ini
expose:
- "8080"
ports:
- "8088:8080"
environment:
ADMINER_DEFAULT_SERVER: mysql
ADMINER_DESIGN: "pappu687"
File php-custom.ini
mình setting tăng giới hạn file upload để import database, không cần cũng được:
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 100M
; Sets max size of post data allowed.
; http://php.net/post-max-size
post_max_size = 120M
Giao diện web quản lý ở địa chị http://localhost:8088
Nếu là lần cài đặt Magento đầu tiên, chúng ta cần chạy command để cài đặt Magento, còn không thì chỉ cần import lại database cũ, nhằm đảm bảo database schema không bị thay đổi (do Magento có nhiều chức năng update qua giao diện web admin).
Lệnh cài đặt cho lần đầu:
# Chạy lệnh trong container php fpm bằng user magento
docker-compose exec -u magento php bash
cd /var/www/html/magento
# Thiết lập lại permissions, trừ thư mục dev/docker vì đây là folder chứa config và data cho docker
find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} + \
&& find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} + \
&& chown -R :www-data $(ls -Idev/docker)
# Cài đặt magento db
php bin/magento setup:install \
--base-url=http://localhost:8011 \
--db-host=mysql \
--db-name=magento_db \
--db-user=magento \
--db-password=secret \
--backend-frontname=admin_mn \
--admin-firstname=admin \
--admin-lastname=admin \
--admin-email=admin@example.com \
--admin-user=admin \
--admin-password=admin123 \
--language=en_US \
--currency=USD \
--timezone=America/Chicago \
--use-rewrites=1
URL: http://localhost:8011 chính là url của web site, do hiện tại chưa có Varnish hay custom domain nên nó là Nginx, vậy nên cần publish port 8011 cho Nginx sau đó để có thể truy cập được website từ host machine.
Địa chỉ admin page: http://localhost:8011/admin_mn
Sau khi chạy lệnh trên Magento sẽ tạo ra 2 file config app/etc/env.php
và app/etc/config.php
. Theo như docs, file env.php
không được thêm vào git, còn config.php
thì nên thêm. Do không được thêm vào git nên chúng ta dựa vào file env.php
để tạo file example chung cho môi trường docker: env.docker-dev-eample.php
.
Redis
Docker config cho redis cũng khá đơn giản:
version: "3"
services:
php:
#...
nginx:
#...
mysql:
#...
redis:
restart: always
image: redis
expose:
- "6379"
Redis được dùng để lưu session và default cache (cũng có thể lưu cả full page cache - FPC). Sau khi chạy service redis, cần update lại file env.php
để config sử dụng redis:
'session' => [
'save' => 'redis',
'redis' => [
'host' => 'redis',
'port' => '6379',
'password' => '',
'timeout' => '2.5',
'persistent_identifier' => '',
'database' => '2',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
'log_level' => '3',
'max_concurrency' => '6',
'break_after_frontend' => '15',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0',
'min_lifetime' => '60',
'max_lifetime' => '2592000',
],
],
'cache' => [
'frontend' => [
'default' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => 'redis',
'database' => '0',
'port' => '6379',
],
],
'page_cache' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => 'redis',
'port' => '6379',
'database' => '1',
'compress_data' => '0',
],
],
],
],
Lưu ý, mỗi loại cache, session thì sẽ có database khác nhau, database 0 cho default cache, database 1 cho FPC và database 2 cho redis.
Config page_cache
để tham chiếu vì chúng ta sẽ dùng Varnish nên config này sẽ bị bỏ qua.
Vào trang admin export file config của Varnish để tiếp tục setup Varnish cache.
Hoặc có thể dùng command để export:
docker-compose exec php bash
php bin/magento varnish:vcl:generate
Varnish
Để lấy file config Varnish mặc định của Magento, chúng ta vào trang admin: http://localhost:8011/admin_mn và đến trang config theo menu: Stores
=> Configuration
=> Advanced
=> System
=> Full Page Cache
Docker compose service:
version: "3"
services:
php:
#...
nginx:
#...
mysql:
#...
redis:
#...
varnish:
restart: always
image: varnish:6
volumes:
- ./dev/docker/images/varnish/default.vcl:/etc/varnish/default.vcl
expose:
- "80"
ports:
- "8011:80"
Vì đã config dùng Varnish nên nginx server giờ đây không cần publish port 8011 nữa mà sẽ để cho Varnish cache làm nhiệm vụ này.
Lưu ý trong file export default.vcl
có đoạn:
backend default {
.host = "nginx";
.port = "80";
.first_byte_timeout = 600s;
.probe = {
.url = "/health_check.php";
...
}
}
Chú ý url để check health là /health_check.php
chứ không phải /pub/health_check.php
do ở phần setting nginx trước, document root đang là root $MAGE_ROOT/pub;
Mail server
Mail server có nhiệm vụ catch tất cả email được gửi trong môi trường dev, để đảm bảo không gửi nhầm email đến địa chỉ thật. Ở đây chúng ta dùng Mailhog
, nó cung cấp SMTP server để gửi mail và một giao diện web ui để đọc các email đã gửi:
version: "3"
services:
php:
#...
nginx:
#...
mysql:
#...
varnish:
#...
redis:
#...
mail-server:
restart: always
image: mailhog/mailhog
user: root # Needed if using maildir
environment:
MH_STORAGE: maildir
MH_MAILDIR_PATH: /var/data/mailhog
volumes:
- ./dev/docker/data/mailhog:/var/data/mailhog
expose:
- "1025" # SMTP Server to send mail
- "8025" # HTTP Server to check mail
ports:
- "8022:8025"
Cần phải cài thêm extension để Magento có thể sử dụng SMTP server, phần này tùy vào khách hàng nên các bạn có thể tự tìm Magento SMTP module.
Mail box ui ở địa chỉ: http://localhost:8022
Như vậy là chúng ta đã thiết lập xong các container image. Tổng kết lại chúng ta đã thêm những file sau:
.
├── app
│ ├── ...
├── dev
│ ├── docker
│ │ ├── env.docker-example.php
│ │ ├── docker-compose.dev.yml
│ │ └── images
│ │ ├── adminer
│ │ │ └── php-custom.ini
│ │ ├── mysql
│ │ │ └── initdb
│ │ │ └── 01-create-db.sql
│ │ ├── nginx
│ │ │ └── magento.conf
│ │ ├── php
│ │ │ ├── Dockerfile
│ │ │ └── php-custom.ini
│ │ └── varnish
│ │ └── default.vcl
Sau khi đã dựng xong phần setup ban đầu, các thành viên khác trong team chỉ cần pull code về và copy các file config:
cp dev/docker/env.docker-example.php app/etc/env.php
cp dev/docker/docker-compose.dev.yml docker-compose.xml
Docker compose up và sau đó import database.
Custom domain và HTTPS
Về custom domain cho service trong Docker có nhiều cách, nhưng hôm nay mình giới thiệu cho các bạn cách đơn giản nhất đó là sử dụng Nginx hoặc Apache ở host machine để tạo reverse proxy đến địa chỉ http://127.0.0.1:8011
.
Luồng hoạt động như thế này:
Ơ nhưng dùng docker rồi vẫn phải cài thêm Apache hay Nginx ở máy thật sao?? =))
Về HTTPS, chúng ta sử dụng tool mkcert
để tạo chứng chỉ SSL hợp lệ cho localhost:
╭─ ubuntu ~/Projects/magento-ee ‹master*›
╰─ $ mkcert -install
Using the local CA at "/home/ubuntu/.local/share/mkcert" ✨
╭─ ubuntu ~/Projects/magento-ee ‹master*›
╰─ $ mkcert magento2.test
Using the local CA at "/home/ubuntu/.local/share/mkcert" ✨
Created a new certificate valid for the following names 📜
- "magento2.test"
The certificate is at "./magento2.test.pem" and the key at "./magento2.test-key.pem" ✅
Lệnh trên generate ra 2 file: magento2.test-key.pem
và magento2.test.pem
sẵn sàng để dùng cho Apache hay Nginx.
Các lệnh và config bên dưới dùng cho Ubuntu, nếu bạn dùng distro khác thì chú ý nhé.
Với Apache, việc đầu tiên là enable proxy http module:
sudo a2enmod proxy_http
Sau đó thêm virtualhost, có thể thiết lập HTTPS only hoặc cả 2:
<VirtualHost *:80>
ProxyPreserveHost On
ServerName magento2.test
ProxyPass / http://127.0.0.1:8011/
ProxyPassReverse / http://127.0.0.1:8011/
</VirtualHost>
<VirtualHost *:443>
SSLEngine On
ProxyPreserveHost On
ProxyRequests Off
ServerName magento2.test
SSLCertificateFile /usr/local/share/ssl/magento2.test.pem
SSLCertificateKeyFile /usr/local/share/ssl/magento2.test-key.pem
ProxyPass / http://127.0.0.1:8011/
ProxyPassReverse / http://127.0.0.1:8011/
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
Restart apache:
sudo systemctl restart apache2.service
Với Nginx:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name magento2.test;
ssl_certificate /usr/local/share/ssl/magento2.test.pem;
ssl_certificate_key /usr/local/share/ssl/magento2.test-key.pem;
location / {
proxy_pass http://127.0.0.1:8011/;
include /etc/nginx/proxy_params;
}
}
Restart nginx:
sudo systemctl restart nginx.service
Tiếp theo là thêm domain vào /etc/hosts
:
127.0.0.1 magento2.test
Bước cuối cùng là update magento base url, từ http://localhost:8011 sang https://magento2.test:
php bin/magento config:set web/unsecure/base_url http://magento2.test/
php bin/magento config:set web/secure/base_url https://magento2.test/
php bin/magento config:set web/secure/use_in_frontend 1
php bin/magento config:set web/secure/use_in_adminhtml 1
php bin/magento cache:flush
Vậy là đã xong. Hẹn gặp lại các bạn trong các bài tiếp theo của series : D
Trên đây là công việc mình config docker lúc ban đầu, bạn nào muốn sử dụng luôn thì xem hướng dẫn ở Github nhé: https://github.com/tuanpht/magento2-docker
All rights reserved