Cách chạy Nginx và PHP trong Docker
Hôm nay chúng ta sẽ thử chạy máy chủ web nginx với PHP 7.4 trong Docker. Chúng tôi sẽ sử dụng Docker, vì chúng tôi sẽ không cài đặt bất kỳ phần mềm nào trên hệ thống máy chủ của chúng tôi. Bạn nên cài đặt Docker và Docker-compo hệ thống của mình. Nếu bạn không biết cách cài đặt Docker và Docker-biên tập, hãy xem bài viết trước của tôi Cách cài đặt Docker trong Linux Mint và Ubuntu .
Tất cả các tệp bạn cần để chạy Nginx và PHP đều có trên Github của tôi . Hãy bắt đầu!
Đầu tiên, chúng ta cần sao chép kho lưu trữ và tạo mạng:
git clone https://github.com/texe/nginxphp
cd nginxphp
docker network create labnet
Tại sao chúng tôi tạo mạng ?. Đó là một câu hỏi rất hay. Trong trường hợp của chúng tôi, chúng tôi làm điều đó, bởi vì chúng tôi muốn có một tình huống mà tất cả các vùng chứa của chúng tôi sẽ được hiển thị cho nhau. Ví dụ, hãy tưởng tượng chúng ta có bốn vùng chứa với bốn dịch vụ:
- PHP
- Nginx
- MySQL
- phpMyAdmin
Và chúng tôi muốn:
- Nginx có thể thấy máy chủ PHP
- Máy chủ PHP sẽ thấy máy chủ MySQL
- phpMyAdmin sẽ thấy máy chủ MySQL
Để làm điều đó, chúng tôi tạo một mạng ảo và mọi dịch vụ trong mạng ảo này sẽ có thể nhìn thấy các dịch vụ khác. Đó là lý do tại sao chúng ta phải tạo một mạng mới trong môi trường docker.
Bây giờ chúng ta phải xây dựng hình ảnh của mình và chúng ta sẽ làm điều đó bằng lệnh này:
docker-compose build
Docker sẽ bắt đầu xây dựng một hình ảnh và tải xuống tất cả các tệp cần thiết. Nó có thể mất một thời gian. Bao nhiêu? Nó phụ thuộc vào kết nối internet của bạn. Hãy cùng xem chi tiết.
Docker kiểm tra tệp docker-compo.yml và thấy rằng chúng tôi muốn xây dựng hình ảnh mới được mô tả trong config / dockerfile. Hãy xem những gì có trong tệp này:
# 1 Set master image
FROM php:7.4-fpm-alpine
# 2 Set working directory
WORKDIR /var/www/html
# 3 Install Additional dependencies
RUN apk update && apk add --no-cache \
build-base shadow vim curl \
php7 \
php7-fpm \
php7-common \
php7-pdo \
php7-pdo_mysql \
php7-mysqli \
php7-mcrypt \
php7-mbstring \
php7-xml \
php7-openssl \
php7-json \
php7-phar \
php7-zip \
php7-gd \
php7-dom \
php7-session \
php7-zlib
# 4 Add and Enable PHP-PDO Extenstions
RUN docker-php-ext-install pdo pdo_mysql mysqli
RUN docker-php-ext-enable pdo_mysql
# 5 Install PHP Composer
#RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# 6 Remove Cache
RUN rm -rf /var/cache/apk/*
# 7 Add UID '1000' to www-data
RUN usermod -u 1000 www-data
# 8 Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www/html
# 9 Change current user to www
USER www-data
# 10 Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
Tôi đã đánh số tất cả các dòng nhận xét và bây giờ giải thích những gì mỗi dòng làm:
- Đây là một hình ảnh cơ sở. Tôi chọn hình ảnh PHP chính thức dựa trên Alpine Linux (php: 7.4-fpm-alpine). Nó rất nhẹ và phân phối nhanh chóng. Tôi luôn lấy Alpine nếu có thể vì hình ảnh dựa trên Ubuntu lớn hơn Alpine rất nhiều.
- Đặt ở đây thư mục làm việc. Không có gì để giải thích ở nơi này…
- Cập nhật kho phần mềm và cài đặt PHP với các phần mở rộng.
- Chúng tôi thêm và kích hoạt trình điều khiển cơ sở dữ liệu. Trong trường hợp này, chúng tôi thêm PDO, PDO MySQL và Mysqli (nó có thể cần thiết cho WordPress).
- Tại đây chúng ta có thể cài đặt Composer. Tôi nhận xét dòng này vì tôi không muốn cài đặt Composer tại thời điểm này. Nhưng nếu bạn muốn sử dụng Composer, bạn có thể bỏ ghi chú dòng này.
- Xóa bộ nhớ cache để tiết kiệm hạn ngạch đĩa.
- Thêm UUID 1000 vào dữ liệu www của người dùng (người dùng Nginx).
- Đặt quyền thư mục cho thư mục có tệp PHP. Chúng tôi cấp quyền truy cập cho mọi người dùng có UUID 1000.
- Thay đổi người dùng hiện tại thành www-data. Đó là người dùng có thể thao tác trên các tệp php của chúng tôi.
- Chúng tôi đưa dịch vụ của mình lên cổng 9000 và chạy máy chủ php-fpm.
Bây giờ chúng ta hãy xem xét tệp docker-compos.yml:
version: '3'
services:
#PHP App
app:
build:
context: .
dockerfile: config/dockerfile
image: christexe/php:7.4-fpm-alpine
container_name: php_app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www/html
volumes:
- ./code/:/var/www/html
- ./config/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
networks:
- labnet
#Nginx Service
nginx:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
tty: true
ports:
- "80:80"
volumes:
- ./code/:/var/www/html
- ./config/conf.d/:/etc/nginx/conf.d/
networks:
- labnet
#Docker Networks
networks:
labnet:
external:
name: labnet
Mỗi dòng có nghĩa là gì?
#PHP App
app:
build:
context: .
dockerfile: config/dockerfile
Điều này có nghĩa là chúng tôi tạo “ứng dụng” dịch vụ đầu tiên. Chúng tôi sẽ xây dựng một hình ảnh mới. Hình ảnh mới sẽ dựa trên dockerfile (trong thư mục “config”). Như tôi đã viết ở trên, Docker phân tích cú pháp mọi dòng trong docker-compost.yml, tìm kiếm dockerfile và xây dựng hình ảnh mới.
Tên của hình ảnh mới sẽ là christexe/php:7.4-fpm-alpine
:.
Tên của vùng chứa sẽ là container_name: php_app
:.
restart: unless-stopped
có nghĩa là vùng chứa PHP của chúng tôi sẽ luôn bắt đầu sau khi khởi động hệ điều hành, trừ khi bạn dừng nó . Nếu bạn dừng vùng chứa này theo cách thủ công, sau khi khởi động lại hệ thống hos, vùng chứa sẽ không tự động khởi động.
tty: true
có nghĩa là chúng tôi muốn có quyền truy cập vào bảng điều khiển (tty) trong máy chủ PHP của chúng tôi. Nó có thể hữu ích khi bạn cần lấy trong thùng chứa.
Bất kỳ lệnh RUN
,, hoặc sẽ được thực thi trong thư mục làm việc được chỉ định .CMD
ADD
COPY
ENTRYPOINT
volumes: - ./code/:/var/www/html - ./config/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
Chúng tôi ánh xạ thư code
mục tới /var/www/html in our container
. Chúng tôi sẽ đặt trong thư mục này tất cả các tệp php (index.php, v.v.).
tệp uploads.ini
thành /usr/local/etc/php/conf.d/uploads.ini
Đây là tệp cấu hình PH mạch. Trong tệp này, chúng tôi cho phép tải lên và giới hạn kích thước tệp tải lên.
networks: - labnet
Chúng tôi chỉ định vùng chứa của mình cho labnet
mạng (đã giải thích ở trên).
Trong dịch vụ nginx, chúng tôi lặp lại hầu hết các tham số của docker. Chúng tôi đã thêm vào đó:
ports: - "80:80"
Chúng tôi chuyển tiếp cổng 80 trong máy chủ của mình đến cổng 80 trong bộ chứa của chúng tôi với nginx. Khối lượng điều khác biệt thứ hai:
volumes: - ./code/:/var/www/html - ./config/conf.d/:/etc/nginx/conf.d/
Chúng tôi lặp lại thư mục ánh xạ code
tới /var/www/html
– đây là thư mục mặc định nơi nginx tìm kiếm các tệp html. Chúng tôi cũng ánh xạ thư config/conf.d
mục tới /etc/nginx/conf.d/
. Đây là thư mục mặc định chứa các tệp cấu hình trang web tìm kiếm nginx. Trong thư mục này, chúng tôi có site.conf
tệp:
server {
listen 80;
server_name VB-Mint20;
# Log files for Debug
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
# Laravel web root directory
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
# Nginx Pass requests to PHP-FPM
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
client_max_body_size 256M;
}
}
Như bạn thấy nginx đang lắng nghe trên cổng 80, tìm kiếm index.php / index.html và phần cuối cùng (Nginx Pass yêu cầu PHP-FPM) kết nối PHP với NGINX. Trong phần này, chúng tôi chỉ ra những gì NGINX nên làm với các tệp php. Dòng cuối cùng trong phần này client_max_body_size 256M; là không bắt buộc nhưng dòng này cho phép tải các tệp lớn (256 MB) lên máy chủ thông qua trình duyệt web.
Đó là tất cả! Bạn có một máy chủ web dày đặc bằng PHP. Mở trình duyệt của bạn và nhập localhost vào thanh địa chỉ của bạn:
Thưởng!
Nếu bạn không muốn xây dựng hình ảnh của riêng mình, bạn có thể tải xuống từ DockerHub . Nhưng cảnh báo! Bạn nên xóa những dòng này khỏi tệp docker-compost.yml:
build:
context: .
dockerfile: config/dockerfile
Sau khi xóa các dòng trên, khi bạn khởi động vùng chứa (docker-soạn lên) Docker sẽ tự động kéo hình ảnh từ Docker Hub. Dockerfile tất nhiên là không cần thiết trong trường hợp này.
Tất cả những gì bạn đọc trong bài viết này, bạn có thể xem trên video của tôi: