Cara Memasang dan Menyediakan Laravel dengan Docker Compose di Ubuntu 22.04


Pengenalan

Untuk mengkontena aplikasi merujuk kepada proses menyesuaikan aplikasi dan komponennya supaya dapat dijalankan dalam persekitaran ringan yang dikenali sebagai kontena. Persekitaran seperti ini bersifat terasing dan boleh dibuang, serta boleh dimanfaatkan untuk membangunkan, menguji, dan menyebarkan aplikasi ke pengeluaran.

Dalam panduan ini, kami akan menggunakan Docker Compose untuk mengkontena aplikasi Laravel bagi tujuan pembangunan. Apabila anda selesai, anda akan mempunyai aplikasi demo Laravel yang berjalan di tiga kontena servis yang berasingan:

  • Perkhidmatan app yang menjalankan PHP7.4-FPM;
  • Perkhidmatan db yang menjalankan MySQL 8.0;
  • Satu perkhidmatan nginx yang menggunakan perkhidmatan app untuk menganalisis kod PHP sebelum menyampaikan aplikasi Laravel kepada pengguna akhir.

Untuk membolehkan proses pembangunan yang lebih lancar dan memudahkan penyahpepijatan aplikasi, kami akan menyimpan fail aplikasi selaras dengan menggunakan volum perkongsian. Kami juga akan melihat bagaimana untuk menggunakan arahan docker compose exec untuk menjalankan Composer dan Artisan di dalam kontena app.

Sebarkan aplikasi frontend anda dari GitHub menggunakan Platform Aplikasi Linux-Console.net. Biarkan Linux-Console.net menumpukan kepada pengembangan aplikasi anda.

Perkara Penting:

  • Containerization menjadikan pembangunan lebih boleh diramalkan: Menjalankan Laravel dalam Docker memastikan persekitaran yang konsisten di seluruh mesin, menghapuskan isu "ia berfungsi di komputer saya" dan memudahkan kerjasama.
  • Pengasingan perkhidmatan meningkatkan kebolehselenggaraan: Memisahkan PHP, MySQL, dan Nginx ke dalam kontena yang berasingan membantu mengasingkan masalah, mempermudah kemas kini, dan meniru tetapan pengeluaran sebenar.
  • Pembolehubah persekitaran adalah penting untuk konfigurasi yang fleksibel: Menggunakan fail .env membolehkan pembangun menukar kelayakan pangkalan data dan tetapan lain tanpa menyentuh kod aplikasi.
  • Imej Docker Tersuai meningkatkan kawalan dan keselamatan: Membina imej PHP anda sendiri memastikan anda hanya memasang apa yang diperlukan oleh projek anda, menjadikan persekitaran ringan dan selamat.
  • Kebenaran fail mesti sepadan dengan pengguna kontena: Menetapkan pemilikan dan kebenaran yang betul untuk direktori boleh tulis Laravel mengelakkan ralat semasa menjalankan dan menyokong pembangunan tempatan yang lancar.
  • Menggunakan fail override menyokong pelbagai persekitaran: docker-compose.override.yml membolehkan penyesuaian tempatan—seperti muat semula secara langsung—tanpa mengubah konfigurasi pengeluaran. Ini memastikan pembangunan dan penyebaran dipisahkan dengan bersih.
  • Penyelesaian masalah bermula dengan memahami tingkah laku kontena: Mengetahui cara memeriksa log, memeriksa perkhidmatan yang sedang berjalan, dan menguji sambungan adalah kunci untuk menyelesaikan kebanyakan masalah dengan cepat dalam tetapan berasaskan kontena.
  • Penyediaan berasaskan Docker berkembang selaras dengan aliran kerja anda: Setelah dibina, konfigurasi yang sama boleh digunakan untuk persekitaran tempatan, percubaan, atau produksi, mewujudkan asas yang stabil dan boleh digunakan semula untuk projek Laravel pada masa hadapan.

Prasyarat

  • Akses ke mesin tempatan Ubuntu atau pelayan pembangunan sebagai pengguna bukan root dengan keistimewaan sudo. Jika anda menggunakan pelayan jarak jauh, adalah disyorkan untuk memasang firewall yang aktif. Untuk menetapkan ini, sila rujuk Panduan Persediaan Pelayan Awal kami untuk Ubuntu.
  • Docker dipasang pada pelayan anda, mengikuti Langkah 1 dan 2 dalam Cara Memasang dan Menggunakan Docker pada Ubuntu.
  • Docker Compose dipasang pada pelayan anda, mengikut Langkah 1 Panduan Cara Memasang dan Menggunakan Docker Compose pada Ubuntu.

Langkah 1 — Mendapatkan Aplikasi Demo

Untuk memulakan, kami akan mengambil aplikasi demo Laravel daripada repositori Githubnya. Kami berminat dengan cawangan tutorial-01, yang mengandungi aplikasi Laravel asas yang telah kami buat dalam panduan Cara Memasang dan Mengkonfigurasi Laravel dengan Nginx pada Ubuntu 22.04 (LEMP).

Untuk mendapatkan kod aplikasi yang serasi dengan tutorial ini, muat turun versi tutorial-1.0.1 ke direktori rumah anda dengan:

cd ~

curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip

Kita akan memerlukan arahan unzip untuk membuka kod aplikasi. Sekiranya anda belum memasang pakej ini sebelum ini, lakukan sekarang dengan:

sudo apt update

sudo apt install unzip

Sekarang, buka kandungan aplikasi dan namakan semula direktori yang dibuka untuk akses yang lebih mudah:

unzip travellist.zip

mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo

Navigasi ke direktori travellist-demo:

cd travellist-demo

Dalam langkah seterusnya, kami akan membuat fail konfigurasi .env untuk menyediakan aplikasi tersebut.

Langkah 2 — Menyediakan Fail .env Aplikasi

Fail konfigurasi Laravel terletak di dalam direktori yang dipanggil config, di dalam direktori akar aplikasi. Selain itu, fail .env digunakan untuk menetapkan konfigurasi bergantung kepada persekitaran, seperti kelayakan dan sebarang maklumat yang mungkin berbeza antara penyebaran. Fail ini tidak termasuk dalam kawalan semakan.

Amaran: Fail konfigurasi persekitaran mengandungi maklumat sensitif tentang pelayan anda, termasuk kelayakan pangkalan data dan kunci keselamatan. Oleh itu, anda tidak sepatutnya berkongsi fail ini secara umum.

Nilai yang terkandung dalam fail .env akan mengutamakan nilai yang ditetapkan dalam fail konfigurasi biasa yang terletak di direktori config. Setiap pemasangan pada persekitaran baru memerlukan fail persekitaran yang disesuaikan untuk menentukan perkara seperti tetapan sambungan pangkalan data, pilihan debug, URL aplikasi, antara item lain yang mungkin berbeza bergantung pada persekitaran tempat aplikasi dijalankan.

Kita akan mencipta fail .env baru untuk menyesuaikan pilihan konfigurasi bagi persekitaran pembangunan yang sedang kita sediakan. Laravel datang dengan contoh fail .env yang boleh kita salin untuk mencipta fail kita sendiri:

cp .env.example .env

Buka fail ini menggunakan nano atau penyunting teks pilihan anda:

nano .env

Fail .env semasa daripada aplikasi demo travellist mengandungi tetapan untuk menggunakan pangkalan data MySQL tempatan, dengan 127.0.0.1 sebagai hos pangkalan data. Kita perlu mengemas kini pembolehubah DB_HOST supaya ia menunjuk kepada perkhidmatan pangkalan data yang akan kita cipta dalam persekitaran Docker kita. Dalam panduan ini, kita akan memanggil perkhidmatan pangkalan data kita sebagai db. Teruskan dan gantikan nilai DB_HOST yang disenaraikan dengan nama perkhidmatan pangkalan data:

APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password
...

Sila juga ubah nama pangkalan data, nama pengguna, dan kata laluan, jika anda mahu. Pembolehubah ini akan digunakan pada langkah seterusnya di mana kita akan menyediakan fail docker-compose.yml untuk mengkonfigurasi perkhidmatan kita.

Simpan fail apabila anda selesai mengedit. Jika anda menggunakan nano, anda boleh melakukannya dengan menekan Ctrl+x, kemudian Y dan Enter untuk mengesahkan.

Langkah 3 – Menyediakan Dockerfile Aplikasi

Walaupun kedua-dua perkhidmatan MySQL dan Nginx kami akan berdasarkan imej lalai yang diperoleh dari Docker Hub, kami masih perlu membina imej tersuai untuk bekas aplikasi. Kami akan mencipta Dockerfile baru untuk itu.

Imej travellist kami akan berdasarkan imej PHP rasmi php:7.4-fpm dari Docker Hub. Di atas persekitaran PHP-FPM asas itu, kami akan memasang beberapa modul PHP tambahan dan alat pengurusan kebergantungan Composer.

Kami juga akan membuat pengguna sistem baru; ini perlu untuk melaksanakan arahan artisan dan composer semasa membangunkan aplikasi. Tetapan uid memastikan bahawa pengguna di dalam kontena mempunyai uid yang sama seperti pengguna sistem anda di mesin hos anda, di mana anda menjalankan Docker. Dengan cara ini, mana-mana fail yang dibuat oleh arahan ini akan direplikasi di hos dengan kebenaran yang betul. Ini juga bermakna anda akan dapat menggunakan penyunting kod pilihan anda di mesin hos untuk membangunkan aplikasi yang dijalankan di dalam kontena.

Buat Dockerfile baru dengan:

nano Dockerfile

Salin kandungan berikut ke dalam Dockerfile anda:

FROM php:7.4-fpm

# Arguments defined in docker-compose.yml
ARG user
ARG uid

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
    chown -R $user:$user /home/$user

# Set working directory
WORKDIR /var/www

USER $user

Jangan lupa untuk menyimpan fail itu setelah selesai.

Dockerfile kami bermula dengan menetapkan imej asas yang kami gunakan: php:7.4-fpm.

Selepas memasang pakej sistem dan sambungan PHP, kami memasang Composer dengan menyalin fail composer yang boleh dijalankan daripada imej rasmi terkini ke imej aplikasi kami sendiri.

Seorang pengguna sistem baru kemudiannya dicipta dan disediakan menggunakan hujah user dan uid yang telah diisytiharkan pada permulaan Dockerfile. Nilai-nilai ini akan disuntik oleh Docker Compose semasa masa binaan.

Akhirnya, kami menetapkan direktori kerja lalai sebagai /var/www dan bertukar ke pengguna yang baru dibuat. Ini akan memastikan anda menyambung sebagai pengguna biasa, dan berada di direktori yang betul, apabila menjalankan perintah composer dan artisan pada kontena aplikasi.

Langkah 4 — Menyediakan Konfigurasi Nginx dan Fail Dump Pangkalan Data

Apabila membuat persekitaran pembangunan dengan Docker Compose, sering kali perlu untuk berkongsi fail konfigurasi atau inisialisasi dengan kontena perkhidmatan, bagi menyiapkan atau memulakan perkhidmatan tersebut. Amalan ini memudahkan melakukan perubahan pada fail konfigurasi untuk menyesuaikan persekitaran anda semasa anda sedang membangunkan aplikasi.

Kita kini akan menyediakan sebuah folder dengan fail-fail yang akan digunakan untuk mengkonfigurasi dan memulakan kontena perkhidmatan kami.

Untuk menyediakan Nginx, kami akan berkongsi fail travellist.conf yang akan mengkonfigurasikan bagaimana aplikasi disajikan. Cipta folder docker-compose/nginx dengan:

mkdir -p docker-compose/nginx

Buka fail baru bernama travellist.conf dalam direktori itu:

nano docker-compose/nginx/travellist.conf

Salin konfigurasi Nginx berikut ke dalam fail itu:

server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    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;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}

Fail ini akan mengkonfigurasi Nginx untuk mendengar pada port 80 dan menggunakan index.php sebagai halaman indeks lalai. Ia akan menetapkan akar dokumen ke /var/www/public, dan kemudian mengkonfigurasi Nginx untuk menggunakan perkhidmatan app pada port 9000 bagi memproses fail *.php.

Simpan dan tutup fail selepas anda selesai mengedit.

Untuk menyediakan pangkalan data MySQL, kami akan berkongsi dump pangkalan data yang akan diimport apabila bekas diinisialisasikan. Ini adalah ciri yang disediakan oleh imej MySQL 8.0 yang akan kami gunakan pada bekas tersebut.

Buat folder baru untuk fail inisialisasi MySQL anda di dalam folder docker-compose:

mkdir docker-compose/mysql

Buka fail .sql yang baharu:

nano docker-compose/mysql/init_db.sql

Dump MySQL berikut berdasarkan pangkalan data yang telah kami sediakan dalam panduan Laravel pada LEMP kami. Ia akan mencipta jadual baru bernama places. Kemudian, ia akan mengisi jadual tersebut dengan set tempat contoh.

Tambahkan kod berikut ke dalam fail:

DROP TABLE IF EXISTS `places`;

CREATE TABLE `places` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `visited` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);

Jadual places mengandungi tiga medan: id, name, dan visited. Medan visited adalah penanda yang digunakan untuk mengenal pasti tempat yang masih belum dikunjungi. Anda boleh menukar tempat contoh atau menambah tempat baru. Simpan dan tutup fail apabila anda selesai.

Kami telah selesai menyediakan Dockerfile aplikasi dan fail konfigurasi perkhidmatan. Seterusnya, kami akan menyediakan Docker Compose untuk menggunakan fail-fail ini semasa mencipta perkhidmatan kami.

Langkah 5 — Mencipta Persekitaran Berbilang Kontena dengan Docker Compose

Docker Compose membolehkan anda mencipta persekitaran berbilang kontena untuk aplikasi yang berjalan di Docker. Ia menggunakan definisi perkhidmatan untuk membina persekitaran yang boleh diubah suai sepenuhnya dengan pelbagai kontena yang boleh berkongsi rangkaian dan volum data. Ini membolehkan integrasi yang lancar antara komponen aplikasi.

Untuk menetapkan definisi perkhidmatan kami, kami akan membuat fail baru bernama docker-compose.yml. Biasanya, fail ini terletak di akar folder aplikasi, dan ia mentakrifkan persekitaran berkanister anda, termasuk imej asas yang akan anda gunakan untuk membina kanister anda, dan bagaimana perkhidmatan anda akan berinteraksi.

Kita akan mentakrifkan tiga perkhidmatan berbeza dalam fail docker-compose.yml kita: app, db, dan nginx.

Perkhidmatan app akan membina imej yang dipanggil travellist, berdasarkan Dockerfile yang telah kita buat sebelumnya. Kontena yang ditakrifkan oleh perkhidmatan ini akan menjalankan server php-fpm untuk memproses kod PHP dan menghantar hasilnya kembali ke perkhidmatan nginx, yang akan dijalankan pada kontena yang berasingan. Perkhidmatan mysql mentakrifkan kontena yang menjalankan server MySQL 8.0. Perkhidmatan kita akan berkongsi rangkaian jambatan bernama travellist.

Fail aplikasi akan diselaraskan pada kedua-dua perkhidmatan app dan nginx melalui bind mounts. Bind mounts berguna dalam persekitaran pembangunan kerana ia membolehkan penyelarasan dua hala yang berprestasi tinggi antara mesin hos dan kontena.

Buat fail docker-compose.yml baru di akar folder aplikasi:

nano docker-compose.yml

Fail docker-compose.yml yang tipikal bermula dengan definisi versi, diikuti dengan nod services, di bawahnya semua perkhidmatan ditakrifkan. Rangkaian yang dikongsi biasanya ditakrifkan di bahagian bawah fail itu.

Untuk memulakan, salin kod asas ini ke dalam fail docker-compose.yml anda:

version: "3.9"
services:


networks:
  travellist:
    driver: bridge

Kita akan mengedit nod services untuk memasukkan perkhidmatan app, db dan nginx.

Perkhidmatan app

Perkhidmatan app akan menyediakan sebuah bekas bernama travellist-app. Ia membina imej Docker baharu berdasarkan Dockerfile yang terletak di laluan yang sama dengan fail docker-compose.yml. Imej baharu ini akan disimpan secara tempatan di bawah nama travellist.

Walaupun akar dokumen yang dilayani sebagai aplikasi terletak di dalam kontena nginx, kita juga memerlukan fail aplikasi di suatu tempat di dalam kontena app, supaya kita dapat menjalankan tugas baris arahan dengan alat Laravel Artisan.

Salin definisi perkhidmatan berikut di bawah nod services anda, di dalam fail docker-compose.yml:

  app:
    build:
      args:
        user: sammy
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    image: travellist
    container_name: travellist-app
    restart: unless-stopped
    working_dir: /var/www/
    volumes:
      - ./:/var/www
    networks:
      - travellist

Tetapan ini melakukan perkara berikut:

  • build: Konfigurasi ini memberitahu Docker Compose untuk membina imej tempatan bagi servis app, menggunakan laluan (konteks) dan Dockerfile yang ditentukan untuk arahan. Argumen user dan uid disuntik ke dalam Dockerfile untuk menyesuaikan arahan penciptaan pengguna pada masa binaan.
  • image: Nama yang akan digunakan untuk imej yang sedang dibina.
  • container_name: Menetapkan nama bekas untuk perkhidmatan ini.
  • restart: Sentiasa mulakan semula, kecuali perkhidmatan dihentikan.
  • working_dir: Menetapkan direktori lalai untuk perkhidmatan ini sebagai /var/www.
  • volumes: Mencipta volume dikongsi yang akan menyegerakkan kandungan dari direktori semasa ke /var/www di dalam kontena. Perhatikan bahawa ini bukan akar dokumen anda, kerana itu akan berada di dalam kontena nginx.
  • rangkaian: Menetapkan perkhidmatan ini untuk menggunakan rangkaian bernama travellist.

Perkhidmatan db

Perkhidmatan db menggunakan imej MySQL 8.0 yang telah dibina daripada Docker Hub. Oleh kerana Docker Compose secara automatik memuatkan fail pembolehubah .env yang terletak di direktori yang sama dengan fail docker-compose.yml, kita boleh mendapatkan tetapan pangkalan data kita daripada fail .env Laravel yang telah kita buat dalam langkah sebelumnya.

Sertakan definisi perkhidmatan berikut dalam nod services anda, tepat selepas perkhidmatan app:

  db:
    image: mysql:8.0
    container_name: travellist-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
    networks:
      - travellist

Tetapan ini melakukan perkara berikut:

  • image: Menentukan imej Docker yang harus digunakan untuk kontena ini. Dalam kes ini, kami menggunakan imej MySQL 8.0 dari Docker Hub.
  • container_name: Menetapkan nama kontena untuk perkhidmatan ini: travellist-db.
  • restart: Sentiasa mulakan semula perkhidmatan ini, kecuali ia dihentikan secara jelas.
  • environment: Menetapkan pemboleh ubah persekitaran dalam kontena baharu. Kami menggunakan nilai yang diperoleh daripada fail .env Laravel untuk menyediakan servis MySQL kami, yang secara automatik akan mencipta pangkalan data dan pengguna baharu berdasarkan pemboleh ubah persekitaran yang diberikan.
  • volumes: Mewujudkan satu volum untuk berkongsi `.sql` dump pangkalan data yang akan digunakan untuk menginisialisasi pangkalan data aplikasi. Imej MySQL akan secara automatik mengimport fail `.sql` yang diletakkan dalam direktori `/docker-entrypoint-initdb.d` di dalam bekas.
  • rangkaian: Menetapkan perkhidmatan ini untuk menggunakan rangkaian bernama travellist.

Perkhidmatan nginx

Perkhidmatan nginx menggunakan imej Nginx yang telah dibina di atas Alpine, satu pengedaran Linux yang ringan. Ia mencipta sebuah kontena bernama travellist-nginx, dan ia menggunakan definisi ports untuk mewujudkan pengalihan dari port 8000 pada sistem hos ke port 80 di dalam kontena.

Sertakan definisi perkhidmatan berikut dalam nod services anda, tepat selepas perkhidmatan db:

  nginx:
    image: nginx:1.17-alpine
    container_name: travellist-nginx
    restart: unless-stopped
    ports:
      - 8000:80
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d
    networks:
      - travellist

Tetapan ini melakukan perkara berikut:

  • image: Menentukan imej Docker yang harus digunakan untuk bekas ini. Dalam kes ini, kami menggunakan imej Alpine Nginx 1.17.
  • container_name: Menetapkan nama bekas untuk perkhidmatan ini: travellist-nginx.
  • restart: Sentiasa mulakan semula perkhidmatan ini, kecuali ia dihentikan secara jelas.
  • ports: Menetapkan pengalihan port yang akan membolehkan akses luaran melalui port 8000 ke pelayan web yang berjalan di port 80 di dalam kontena.
  • volumes: Mencipta dua volume perkongsian. Volume pertama akan menyelaraskan kandungan daripada direktori semasa ke /var/www di dalam kontena. Dengan cara ini, apabila anda membuat perubahan tempatan pada fail aplikasi, ia akan segera tercermin dalam aplikasi yang dihidangkan oleh Nginx di dalam kontena. Volume kedua akan memastikan fail konfigurasi Nginx kami, yang terletak di docker-compose/nginx/travellist.conf, disalin ke folder konfigurasi Nginx kontena.
  • rangkaian: Menyediakan perkhidmatan ini untuk menggunakan rangkaian bernama travellist.

Selesai docker-compose.yml Fail

Beginilah rupa fail docker-compose.yml yang telah siap:

version: "3.9"
services:
  app:
    build:
      args:
        user: sammy
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    image: travellist
    container_name: travellist-app
    restart: unless-stopped
    working_dir: /var/www/
    volumes:
      - ./:/var/www
    networks:
      - travellist

  db:
    image: mysql:8.0
    container_name: travellist-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
    networks:
      - travellist

  nginx:
    image: nginx:1.17-alpine
    container_name: travellist-nginx
    restart: unless-stopped
    ports:
      - 8000:80
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d/
    networks:
      - travellist

networks:
  travellist:
    driver: bridge

Pastikan anda menyimpan fail itu apabila anda selesai.

Langkah 6 — Menjalankan Aplikasi dengan Docker Compose

Kita sekarang akan menggunakan perintah docker compose untuk membina imej aplikasi dan menjalankan perkhidmatan yang telah kita nyatakan dalam tetapan kita.

Bina imej app dengan arahan berikut:

docker compose build app

Arahan ini mungkin mengambil beberapa minit untuk diselesaikan. Anda akan melihat output yang serupa dengan ini:

Building app
Sending build context to Docker daemon  377.3kB
Step 1/11 : FROM php:7.4-fpm
 ---> 8c08d993542f
Step 2/11 : ARG user
 ---> e3ce3af04d87
Step 3/11 : ARG uid
 ---> 30cb921ef7df
Step 4/11 : RUN apt-get update && apt-get install -y     git     curl     libpng-dev     libonig-dev     libxml2-dev     zip     unzip
. . .
 ---> b6dbc7a02e95
Step 5/11 : RUN apt-get clean && rm -rf /var/lib/apt/lists/*
 ---> 10ef9dde45ad
. . .
Step 6/11 : RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
. . .
 ---> 920e4f09ec75
Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
 ---> dbbcd44e44af
Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user
 ---> db98e899a69a
Step 9/11 : RUN mkdir -p /home/$user/.composer &&     chown -R $user:$user /home/$user
 ---> 5119e26ebfea
Step 10/11 : WORKDIR /var/www
 ---> 699c491611c0
Step 11/11 : USER $user
 ---> cf250fe8f1af
Successfully built cf250fe8f1af
Successfully tagged travellist:latest

Apabila binaan selesai, anda boleh menjalankan persekitaran dalam mod latar belakang dengan:

docker compose up -d
Creating travellist-db    ... done
Creating travellist-app   ... done
Creating travellist-nginx ... done

Ini akan menjalankan bekas anda di latar belakang. Untuk menunjukkan maklumat tentang keadaan perkhidmatan aktif anda, jalankan:

docker compose ps

Anda akan melihat output seperti ini:

      Name                    Command              State                  Ports                
-----------------------------------------------------------------------------------------------
travellist-app     docker-php-entrypoint php-fpm   Up      9000/tcp                            
travellist-db      docker-entrypoint.sh mysqld     Up      3306/tcp, 33060/tcp                 
travellist-nginx   nginx -g daemon off;            Up      0.0.0.0:8000->80/tcp,:::8000->80/tcp

Persekitaran anda kini sedang berjalan.

Anda kini boleh mengesahkan bahawa setiap perkhidmatan berkontena bertindak balas dengan betul menggunakan arahan curl yang mudah.

  1. Untuk menguji perkhidmatan web Nginx:

    curl -I http://localhost:8000

    Output yang dijangka:

    HTTP/1.1 200 OK
    Server: nginx/1.17.10
    Content-Type: text/html; charset=UTF-8

    Ini mengesahkan bahawa kontena Nginx sedang berjalan dan memberikan respons dari aplikasi Laravel anda.

  2. Untuk menguji PHP-FPM melalui Nginx:

    curl -s http://localhost:8000 | grep "Berlin"

    Jika aplikasi berjalan dengan betul, arahan ini akan memaparkan HTML halaman selamat datang yang termasuk perkataan Berlin.

Kita masih perlu melaksanakan beberapa arahan untuk menyelesaikan penyediaan aplikasi. Anda boleh menggunakan arahan docker compose exec untuk melaksanakan arahan dalam bekas perkhidmatan, seperti ls -l untuk menunjukkan maklumat terperinci mengenai fail dalam direktori aplikasi:

docker compose exec app ls -l
total 256
-rw-r--r-- 1 sammy sammy    737 Apr 18 14:21 Dockerfile
-rw-r--r-- 1 sammy sammy    101 Jan  7  2020 README.md
drwxr-xr-x 6 sammy sammy   4096 Jan  7  2020 app
-rwxr-xr-x 1 sammy sammy   1686 Jan  7  2020 artisan
drwxr-xr-x 3 sammy sammy   4096 Jan  7  2020 bootstrap
-rw-r--r-- 1 sammy sammy   1501 Jan  7  2020 composer.json
-rw-r--r-- 1 sammy sammy 179071 Jan  7  2020 composer.lock
drwxr-xr-x 2 sammy sammy   4096 Jan  7  2020 config
drwxr-xr-x 5 sammy sammy   4096 Jan  7  2020 database
drwxr-xr-x 4 sammy sammy   4096 Apr 18 14:22 docker-compose
-rw-r--r-- 1 sammy sammy   1017 Apr 18 14:29 docker-compose.yml
-rw-r--r-- 1 sammy sammy   1013 Jan  7  2020 package.json
-rw-r--r-- 1 sammy sammy   1405 Jan  7  2020 phpunit.xml
drwxr-xr-x 2 sammy sammy   4096 Jan  7  2020 public
-rw-r--r-- 1 sammy sammy    273 Jan  7  2020 readme.md
drwxr-xr-x 6 sammy sammy   4096 Jan  7  2020 resources
drwxr-xr-x 2 sammy sammy   4096 Jan  7  2020 routes
-rw-r--r-- 1 sammy sammy    563 Jan  7  2020 server.php
drwxr-xr-x 5 sammy sammy   4096 Jan  7  2020 storage
drwxr-xr-x 4 sammy sammy   4096 Jan  7  2020 tests
-rw-r--r-- 1 sammy sammy    538 Jan  7  2020 webpack.mix.js

Kita kini akan menjalankan composer install untuk memasang pergantungan aplikasi:

docker compose exec app rm -rf vendor composer.lock

docker compose exec app composer install

Anda akan melihat output seperti ini:

No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
. . .
Lock file operations: 89 installs, 0 updates, 0 removals
  - Locking doctrine/inflector (2.0.4)
  - Locking doctrine/instantiator (1.4.1)
  - Locking doctrine/lexer (1.2.3)
  - Locking dragonmantank/cron-expression (v2.3.1)
  - Locking egulias/email-validator (2.1.25)
  - Locking facade/flare-client-php (1.9.1)
  - Locking facade/ignition (1.18.1)
  - Locking facade/ignition-contracts (1.0.2)
  - Locking fideloper/proxy (4.4.1)
  - Locking filp/whoops (2.14.5)
. . .
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 89 installs, 0 updates, 0 removals
  - Downloading doctrine/inflector (2.0.4)
  - Downloading doctrine/lexer (1.2.3)
  - Downloading dragonmantank/cron-expression (v2.3.1)
  - Downloading symfony/polyfill-php80 (v1.25.0)
  - Downloading symfony/polyfill-php72 (v1.25.0)
  - Downloading symfony/polyfill-mbstring (v1.25.0)
  - Downloading symfony/var-dumper (v4.4.39)
  - Downloading symfony/deprecation-contracts (v2.5.1)
. . .
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

Perkara terakhir yang perlu kita lakukan sebelum menguji aplikasi ialah menjana kunci aplikasi unik menggunakan alat baris perintah artisan Laravel. Kunci ini digunakan untuk menyulitkan sesi pengguna dan data sensitif lain:

docker compose exec app php artisan key:generate
Application key set successfully.

Sekarang pergi ke pelayar anda dan akses nama domain atau alamat IP pelayan anda di port 8000:

http://server_domain_or_IP:8000

Nota: Sekiranya anda menjalankan demo ini di komputer anda, gunakan http://localhost:8000 untuk mengakses aplikasi dari pelayar anda.

Anda akan melihat halaman seperti ini:

Anda juga boleh menguji aplikasi Laravel dari dalam bekas aplikasi tanpa menggunakan pelayar:

docker compose exec app curl http://nginx

Jika semuanya dikonfigurasi dengan betul, anda sepatutnya dapat melihat output HTML bagi halaman sambutan lalai Laravel.

<html>
<head>
    <title>Travel List</title>
</head>

<body>
    <h1>My Travel Bucket List</h1>
    <h2>Places I'd Like to Visit</h2>
    <ul>
        <li>Berlin</li>
        <li>Budapest</li>
        <li>Denver</li>
        <li>Helsinki</li>
        <li>Lisbon</li>
        <li>Nairobi</li>
        <li>Rio</li>
        <li>Tokyo</li>
    </ul>

    <h2>Places I've Already Been To</h2>
    <ul>
        <li>Cincinnati</li>
        <li>Moscow</li>
        <li>Oslo</li>
    </ul>
</body>
</html>

Anda boleh menggunakan perintah logs untuk memeriksa log yang dijana oleh perkhidmatan anda:

docker compose logs nginx
Attaching to travellist-nginx
. . .
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:49:16 +0000] "GET / HTTP/1.1" 200 627 "-" "curl/7.82.0"
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"

Anda juga boleh menggunakan arahan curl berikut untuk mencetuskan entri log:

curl http://localhost:8000

Kemudian jalankan semula:

docker compose logs nginx

Anda kini sepatutnya dapat melihat entri log akses yang sepadan untuk permintaan anda.

Jika anda ingin menjeda persekitaran Docker Compose anda sambil mengekalkan keadaan semua servisnya, jalankan:

docker compose pause
Pausing travellist-db    ... done
Pausing travellist-nginx ... done
Pausing travellist-app   ... done

Anda kemudian boleh menyambung kembali perkhidmatan anda dengan:

docker compose unpause
Unpausing travellist-app   ... done
Unpausing travellist-nginx ... done
Unpausing travellist-db    ... done

Untuk menutup persekitaran Docker Compose anda dan menghapus semua kontena, rangkaian, serta volumnya, jalankan:

docker compose down
Stopping travellist-nginx ... done
Stopping travellist-db    ... done
Stopping travellist-app   ... done
Removing travellist-nginx ... done
Removing travellist-db    ... done
Removing travellist-app   ... done
Removing network travellist-laravel-demo_travellist

Untuk tinjauan semua arahan Docker Compose, sila semak rujukan baris arahan Docker Compose.

Memperbaiki Kebenaran Fail dan Direktori Laravel

Apabila menjalankan Laravel di dalam kontena Docker, salah satu isu yang paling biasa dihadapi oleh pembangun berkaitan dengan kebenaran fail dan direktori. Laravel memerlukan beberapa direktori untuk boleh ditulis oleh proses PHP-FPM di dalam kontena app. Jika direktori ini tidak boleh ditulis, aplikasi mungkin gagal mencatat ralat, menyimpan fail konfigurasi cache, atau menyimpan data sesi dengan betul.

Anda mungkin akan menemui mesej seperti:

The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

atau

file_put_contents(/var/www/bootstrap/cache/config.php): Failed to open stream: Permission denied

Ralat ini menunjukkan bahawa pengguna yang menjalankan PHP dalam bekas tidak mempunyai kebenaran untuk menulis ke direktori yang diperlukan.

Langkah-langkah berikut menerangkan cara untuk mendiagnosis dan membaiki masalah ini di kedua-dua persekitaran tempatan dan produksi.

Laraskan Kebenaran Direktori Boleh Tulis

Laravel memerlukan dua direktori untuk boleh ditulis oleh pengguna pelayan web:

  • /var/www/storage
  • /var/www/bootstrap/cache

Jika anda melihat ralat kebenaran, anda boleh membetulkannya dengan menyesuaikan pemilikan dan kebenaran dari dalam bekas:

docker compose exec app chown -R sammy:sammy /var/www/storage /var/www/bootstrap/cache

docker compose exec app chmod -R 775 /var/www/storage /var/www/bootstrap/cache

Jika Dockerfile anda menggunakan nama pengguna yang berbeza (ditentukan melalui argumen binaan user), gantikan sammy dengan nama pengguna tersebut.

Anda boleh mengesahkan pemilikan dengan arahan berikut:

docker compose exec app ls -ld /var/www/storage /var/www/bootstrap/cache

Output seharusnya menunjukkan bahawa pengguna dan kumpulan sepadan dengan proses PHP-FPM di dalam kontena.

Jika anda ingin menyesuaikan kebenaran dari mesin hos sebaliknya, jalankan:

sudo chown -R $(id -u):$(id -g) storage bootstrap/cache

sudo chmod -R 775 storage bootstrap/cache

Ini memastikan bahawa kedua-dua direktori Laravel boleh ditulis oleh bekas dan pengguna hos anda.

Tetapkan Pemilikan Direktori Semasa Membangun Imej

Untuk mengelakkan masalah kebenaran berulang selepas setiap binaan semula, anda boleh menetapkan pemilikan direktori semasa proses binaan imej Docker. Buka Dockerfile anda dan tambah baris berikut berhampiran penghujung, sebelum bertukar ke pengguna bukan root:

RUN chown -R $user:www-data /var/www

Perintah ini memastikan bahawa semua fail dan direktori di bawah /var/www dimiliki oleh pengguna yang anda tetapkan dalam Dockerfile anda.

Untuk pendekatan yang lebih terarah dan selamat, anda boleh menyesuaikan hanya direktori yang perlu ditulis oleh Laravel:

RUN chown -R $user:www-data /var/www/storage /var/www/bootstrap/cache

Selepas membuat perubahan ini, bina semula imej dan mulakan semula bekas:

docker compose build app

docker compose up -d

Kali berikutnya bekas itu dimulakan, ia akan mempunyai kebenaran yang betul.

Sahkan Konsistensi ID Pengguna Antara Hos dan Kontena

Apabila menggunakan bind mounts, Docker berkongsi fail antara hos anda dan bekas. Jika UID berangka pengguna hos berbeza daripada UID yang ditentukan dalam bekas, konflik pemilikan fail mungkin berlaku. Ini adalah perkara biasa pada sistem di mana ID pengguna berbeza antara mesin.

Untuk mengesahkan nilai UID, jalankan:

id -u $(whoami)

docker compose exec app id -u

Jika kedua-dua nombor ini tidak sepadan, kemas kini fail docker-compose.yml anda untuk memindahkan UID sebenar anda ke proses binaan:

build:
  args:
    user: sammy
    uid: 1000

Kemudian bina semula imej itu:

docker compose build app

docker compose up -d

Ini memastikan bahawa pengguna kontena sepadan dengan pengguna hos anda, mengelakkan ketidakpadanan kebenaran pada fail yang dipasang secara bind.

Betulkan Kebenaran Direktori Cache Composer

Composer menyimpan kebergantungan yang dimuat turun dan fail cache di direktori rumah pengguna di dalam kontena (/home/sammy/.composer). Jika direktori ini tidak boleh ditulis, anda mungkin akan melihat amaran seperti:

Cannot create cache directory /home/sammy/.composer/cache

Anda boleh membetulkannya dengan membuat direktori cache dan menetapkan hak milik yang betul:

docker compose exec app mkdir -p /home/sammy/.composer/cache

docker compose exec app chown -R sammy:sammy /home/sammy/.composer

Ini memastikan bahawa Composer boleh menyimpan kebergantungan dan fail cache tanpa ralat kebenaran, yang juga mempercepatkan pelaksanaan composer install pada masa hadapan.

Amalan Disyorkan untuk Persekitaran Pengeluaran

Dalam pengeluaran, pengurusan kebenaran harus dikendalikan semasa pembinaan imej dan bukannya semasa masa jalan. Ini meningkatkan konsistensi dan keselamatan.

Ikuti amalan ini untuk konfigurasi yang sedia untuk pengeluaran:

  • Elakkan bind mount untuk kod aplikasi: Sebaliknya, salin fail aplikasi ke dalam imej semasa proses binaan. Bind mount harus dikhaskan untuk pembangunan.

  • Tetapkan kebenaran semasa binaan: Tambahkan arahan RUN chown dan chmod ke dalam Dockerfile anda untuk memastikan pemilikan dan hak akses yang betul sebelum penghantaran.

  • Gunakan pengguna dengan hak paling rendah: Pastikan proses PHP dijalankan di bawah pengguna bukan root (susunan semasa dengan $user sudah melakukan ini).

  • Sekat kebenaran pada direktori yang tidak boleh ditulis: Kebanyakan fail aplikasi sepatutnya hanya baca sahaja. Anda boleh menguatkuasakan ini dengan:

    chmod -R 755 /var/www
    
    chmod -R 775 /var/www/storage /var/www/bootstrap/cache

    Tetapan ini membolehkan Laravel menulis hanya di tempat yang perlu sambil melindungi fail aplikasi lain daripada diubah.

Dengan mengikuti langkah-langkah ini, bekas Laravel anda akan mempunyai kebenaran fail yang stabil dan boleh dijangka dalam persekitaran tempatan dan pengeluaran. Ini mengurangkan ralat yang berulang dan memastikan Laravel boleh merekod data, menyimpan fail cache, dan menulis sesi dengan boleh dipercayai.

Memahami docker-compose.override.yml untuk Persekitaran Tempatan dan Produksi

Docker Compose membolehkan anda mentakrifkan aplikasi berbilang kontena menggunakan satu fail konfigurasi. Dalam kebanyakan kes, konfigurasi ini disimpan dalam fail bernama docker-compose.yml. Walau bagaimanapun, menguruskan pelbagai persekitaran seperti pembangunan tempatan dan pengeluaran, sering memerlukan penyesuaian khusus persekitaran. Di sinilah fail docker-compose.override.yml menjadi berguna.

Secara lalai, Docker Compose secara automatik mencari fail bernama docker-compose.override.yml dalam direktori yang sama dengan fail Compose asas. Apabila dijumpai, ia menggabungkan konfigurasi dari kedua-dua fail apabila anda menjalankan mana-mana arahan docker compose. Pendekatan ini membolehkan pembangun mengekalkan konfigurasi asas yang bersih dan boleh digunakan semula sambil menyesuaikan aspek tertentu bagi penggunaan tempatan atau pengeluaran.

Peranan docker-compose.override.yml

Fail docker-compose.override.yml adalah lanjutan kepada konfigurasi Compose asas. Ia mengubah atau menambah sifat yang hanya terpakai kepada persekitaran tertentu, tanpa memerlukan perubahan pada fail utama docker-compose.yml. Fail override ini sangat berguna dalam aliran kerja pembangunan tempatan, di mana pembangun sering perlu memasang kod sumber, mengaktifkan alat debugging, atau mengubah pembolehubah persekitaran untuk ujian.

Apabila anda menjalankan perintah docker compose up, Docker secara automatik menggabungkan kandungan docker-compose.yml dan docker-compose.override.yml. Jika sesuatu perkhidmatan, volum, atau konfigurasi ditakrifkan dalam kedua-dua fail, nilai dalam fail override akan diutamakan.

Untuk menggunakan fail override yang berbeza, contohnya, satu yang dimaksudkan untuk produksi, anda boleh menentukan fail tersebut secara manual menggunakan bendera -f:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Pendekatan ini membolehkan anda mengekalkan konfigurasi berasingan untuk persekitaran yang berbeza sambil menggunakan struktur arahan yang konsisten.

Menyusun untuk Pembangunan Tempatan

Persekitaran pembangunan tempatan biasanya memerlukan perubahan yang kerap, pemuatan semula kod secara langsung, dan log yang terperinci. Fail docker-compose.override.yml membolehkan ciri-ciri ini diperkenalkan tanpa menjejaskan persekitaran lain.

Fail override tempatan yang tipikal mungkin termasuk:

  • Pemasangan bind untuk kemas kini kod secara langsung
  • Arahan binaan tempatan dan bukannya menggunakan imej yang telah dibina
  • Pembolehubah persekitaran khusus pembangunan
  • Perkhidmatan penyahpepijatan dan ujian

Sebagai contoh:

version: "3.9"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./src:/app
      - ./logs:/app/logs
    environment:
      - DATABASE_URL=postgres://postgres:postgres@db:5432/app_db
      - LOG_LEVEL=debug
    ports:
      - "8000:8000"
    depends_on:
      - db

  db:
    environment:
      - POSTGRES_PASSWORD=postgres

Dalam contoh ini:

  • Perkhidmatan app dibina terus dari Dockerfile tempatan (Dockerfile.dev), menjadikannya mudah untuk menguji perubahan tanpa membina semula imej melalui registri.
  • Kod sumber dipasang menggunakan bind mount, membolehkan bekas mencerminkan perubahan fail tempatan secara masa nyata.
  • Pemboleh ubah persekitaran seperti LOG_LEVEL=debug ditetapkan untuk memberikan output yang lebih terperinci semasa pembangunan.
  • Pangkalan data menggunakan kelayakan yang mudah yang sesuai untuk ujian tempatan tetapi tidak boleh digunakan dalam pengeluaran.

Konfigurasi ini menyediakan persekitaran pembangunan yang lebih pantas dan fleksibel sambil mengekalkan konfigurasi asas tanpa perubahan.

Bersedia untuk Pengeluaran

Persekitaran pengeluaran memerlukan kestabilan, keterulangan, dan keselamatan. Kontena harus dijalankan daripada imej yang telah dibina terlebih dahulu daripada dibina secara tempatan, dan maklumat sensitif harus diurus dengan selamat. Tidak seperti fail override yang digunakan secara automatik untuk pembangunan tempatan, override untuk pengeluaran mesti ditentukan secara jelas.

Fail override produksi (docker-compose.prod.yml) biasanya direka untuk menggantikan langkah binaan tempatan dengan rujukan imej, menggunakan volum bernama menggantikan mount bind, dan menetapkan sifat berkaitan penyebaran seperti had sumber dan penskalaan.

Contoh:

version: "3.9"

services:
  app:
    image: registry.example.com/myapp:1.2.3
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - LOG_LEVEL=info
    volumes:
      - app-data:/var/lib/app
    ports:
      - "8000:8000"
    restart: unless-stopped
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M

  db:
    image: postgres:15
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password

secrets:
  db_password:
    external: true

volumes:
  app-data:
  db-data:

Dalam konfigurasi ini:

  • Perkhidmatan app merujuk kepada imej yang telah dibina (myapp:1.2.3) yang disimpan dalam registri dan bukannya dibina secara tempatan.

  • Pemasangan bind digantikan dengan volum bernama untuk memastikan penyimpanan data yang konsisten dan terasing.

  • Kredensial sensitif disimpan dengan selamat menggunakan Docker secrets.

  • Bahagian deploy menentukan tingkah laku penalaan dan had sumber untuk kestabilan yang lebih baik semasa beban tinggi.

  • Konfigurasi mesti diterapkan secara jelas semasa penyebaran:

    docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Struktur ini memastikan bahawa pengeluaran pelaksanaan adalah konsisten, terkawal, dan bebas daripada artifak pembangunan tempatan.

Membandingkan Penggantian Tempatan dan Pengeluaran

Aspek KonfigurasiTempatan (docker-compose.override.yml)Pengeluaran (docker-compose.prod.yml)
Diterapkan secara automatikYaTidak (mesti gunakan -f)
Pengendalian kod sumberPemasangan bind untuk kemas kini langsungImej terpasang dari registri
Pembolehubah persekitaranNilai berfokus pada pemajuNilai selamat untuk pengeluaran
PembalakanVerbose (debug)Ringkas (info atau error)
Pengurusan rahsiaNilai biasa atau .envRahsia Docker atau rahsia yang diurus
PenimbanganBekas tunggalPelbagai salinan
Penyelarasan prestasiTidak diperlukanHad sumber ditetapkan
Alat penyahpepijatDihidupkanKurang Upaya
Polisi mulakan semulaManual atau tiada
restart: unless-stopped

Menggunakan beberapa fail Docker Compose menyediakan cara yang bersih untuk memisahkan konfigurasi khusus persekitaran daripada tetapan asas. Fail asas docker-compose.yml menentukan struktur aplikasi yang sama, manakala docker-compose.override.yml menyesuaikannya untuk pembangunan tempatan. Apabila menyiarkan ke produksi, fail override yang jelas memastikan konfigurasi yang boleh diramalkan dan selamat.

Corak ini membolehkan pasukan mengekalkan aliran kerja yang konsisten. Pembangun boleh memulakan aplikasi secara tempatan menggunakan:

docker compose up

dan terapkan ke produksi menggunakan:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Kedua-dua persekitaran berkongsi konfigurasi teras yang sama sambil mengekalkan tetapan yang bebas sesuai untuk keperluan khusus mereka. Pemisahan ini meningkatkan kebolehselenggaraan, mengurangkan kesilapan konfigurasi, dan memastikan persekitaran tempatan dan produksi selaras.

Menyelesaikan Masalah Persekitaran Anda

Bahagian ini menyediakan langkah penyelesaian masalah untuk masalah biasa yang mungkin anda hadapi semasa menjalankan aplikasi anda dengan Docker Compose.

502 Pintu Gerbang Buruk (Nginx menunjukkan respons 502)

Gejala:

  • Pelayar menunjukkan 502 Bad Gateway semasa mengakses http://localhost:8000.
  • Log Nginx mengandungi baris seperti recv() gagal (111: Sambungan ditolak) atau connect() gagal (111: Sambungan ditolak) semasa menyambung ke huluan.

Punca kemungkinan:

  • PHP-FPM (perkhidmatan app) tidak berjalan atau tidak mendengar pada soket/port yang dijangkakan.
  • Nginx fastcgi_pass menunjuk ke hos/port yang salah.
  • Ketidakcocokan nama kontena atau masalah rangkaian antara nginx dan app.
  • app terhenti ketika mula dijalankan (contohnya, kerana sambungan hilang atau ralat konfigurasi).

Cara mengesahkan:

  1. Periksa log Nginx:

    docker compose logs nginx | tail -n 100

    Cari mesej 502 atau ralat sambungan huluan.

  2. Periksa status dan log kontena app:

    docker compose ps app
    
    docker compose logs app --tail=200
  3. Sahkan PHP-FPM sedang mendengar di dalam kontena app:

    docker compose exec app ss -ltnp | grep :9000 || docker compose exec app ss -lxp | grep php-fpm

    Dijangka: sama ada pendengar TCP pada port 9000 atau soket Unix yang digunakan oleh nginx (kurang biasa dengan kompos ini).

  4. Sahkan nginx boleh menyelesaikan dan mencapai app di rangkaian kompos:

    docker compose exec nginx ping -c 2 app
    
    docker compose exec nginx wget -qO- --timeout=2 http://app:9000/ || true

    Jika ping gagal atau wget tamat masa, terdapat masalah rangkaian atau ketidakpadanan nama perkhidmatan.

Pembaikan biasa:

  • Jika PHP-FPM tidak berjalan, periksa log app untuk ralat PHP yang kritikal atau kegagalan semasa permulaan. Betulkan ralat asas (selalunya sambungan hilang atau masalah kebenaran) dan mulakan semula:

    docker compose restart app
    
    docker compose logs app --tail=100
  • Jika konfigurasi Nginx menggunakan upstream yang berbeza (contohnya, fastcgi_pass 127.0.0.1:9000;), kemaskini docker-compose/nginx/travellist.conf kepada fastcgi_pass app:9000; (mengikut nama servis compose anda) dan muat semula Nginx:

    # After editing config in host
    
    docker compose exec nginx nginx -s reload
    
    docker compose logs nginx --tail=50
  • Jika PHP-FPM mendengar pada soket Unix (contoh, /run/php/php7.4-fpm.sock) tetapi Nginx menjangkakan TCP atau sebaliknya, tetapkan standard kepada TCP app:9000 untuk tetapan Compose atau pasangkan soket dengan betul antara kontena (disyorkan: gunakan TCP dalam Compose pelbagai kontena).

Sambungan PHP hilang (ralat semasa menjalankan Composer atau Artisan, atau kegagalan semasa runtime)

Gejala:

  • Perintah Composer atau Laravel gagal dengan mesej seperti Kelas "PDO" tidak ditemui, ext-pdo tiada, atau Panggilan kepada fungsi json_encode yang tidak ditentukan.
  • Ralat PHP dalam log app yang merujuk kepada kelas atau fungsi yang tidak ditakrifkan.

Cara mengesahkan:

  1. Periksa senarai modul PHP kontena app:

    docker compose exec app php -m | sort

    Cari nama sambungan yang anda perlukan (untuk sambungan tipikal Laravel: pdo_mysql, mbstring, bcmath, openssl, tokenizer, xml, ctype, json, gd).

  2. Periksa teks ralat composer yang biasanya menyenaraikan sambungan yang diperlukan:

    docker compose exec app composer install

Pembaikan:

  • Tambahkan sambungan yang hilang dalam Dockerfile anda dan bina semula imej tersebut. Contoh (untuk pdo_mysql dan gd):

    RUN apt-get update && apt-get install -y libpng-dev libxml2-dev \
        && docker-php-ext-install pdo_mysql mbstring xml gd

    Kemudian bina semula dan mulakan semula:

    docker compose build app
    
    docker compose up -d app
    
    docker compose logs app --tail=100
  • Jika sesebuah sambungan memerlukan perpustakaan sistem (contohnya gd memerlukan libpng-dev), tambah baris apt-get install yang sepadan sebelum docker-php-ext-install.

  • Jika anda memerlukan sambungan PHP yang tidak tersedia secara lalai, pertimbangkan untuk memasangnya melalui PECL dan aktifkannya dalam php.ini.

Kegagalan sambungan pangkalan data (Laravel tidak dapat menyambung ke MySQL)

Gejala:

  • Laravel menunjukkan ralat sambungan pangkalan data (SQLSTATE[HY000] [2002] Sambungan ditolak atau Akses ditolak untuk pengguna).
  • Migrasi gagal, atau aplikasi menunjukkan halaman kosong untuk halaman berasaskan data.

Cara mengesahkan:

  1. Semak log kontena DB untuk ralat inisialisasi:

    docker compose logs db --tail=200
  2. Sahkan bekas DB sedang berjalan:

    docker compose ps db
  3. Sahkan bahawa kelayakan dan hos adalah konsisten antara .env dan docker-compose.yml. Dalam .env Laravel, DB_HOST sepatutnya nama perkhidmatan compose (db), bukan 127.0.0.1 atau localhost:

    DB_HOST=db
    DB_PORT=3306
    DB_DATABASE=travellist
    DB_USERNAME=travellist_user
    DB_PASSWORD=password
  4. Ujian dari dalam bekas db:

    docker compose exec db mysql -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e "SHOW DATABASES;"

    Atau, ujikan dari kontena app untuk memastikan kesambungan rangkaian:

    docker compose exec app sh -c 'which mysql >/dev/null 2>&1 || echo "no mysql client"; mysql -h db -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e "SELECT VERSION();"'

Punca dan penyelesaian biasa:

  • Hos salah dalam .env: kemas kini DB_HOST=db, cipta semula kontena atau muat semula envs:

    docker compose down
    
    docker compose up -d
    
    docker compose exec app php artisan migrate
  • Pangkalan data tidak sedia apabila aplikasi dimulakan: gunakan mekanisme cuba semula dalam aplikasi anda atau tambah pemeriksaan kesihatan dan mula membuat pesanan. Anda juga boleh menunggu secara manual:

    docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping
    
    # expected: mysqld is alive
  • Inisialisasi SQL gagal: semak fail di bawah ./docker-compose/mysql, ralat sintaks atau kebenaran boleh menghentikan inisialisasi DB. Periksa log DB untuk ralat import.

  • Kelebihan/kelayakan salah: sahkan pangkalan data dan pengguna wujud. Buat semula pangkalan data atau jalankan SQL untuk memberikan kelebihan.

  • Penggunaan port di peringkat hos: jika anda mencuba curl telnet://localhost:3306 dan perkhidmatan db tidak mendedahkan port hos, sambungan itu akan ditolak secara sengaja. Uji dari dalam kontena, atau dedahkan port dalam docker-compose.yml (ports: - "3306:3306") untuk debugging setempat sahaja.

Masalah kebenaran dan sistem fail (penyimpanan, cache, fail log)

Gejala:

  • Laravel melempar pengecualian berkaitan dengan penulisan cache atau log: Aliran atau fail "/var/www/storage/logs/laravel.log" tidak dapat dibuka.
  • Fail yang dicipta oleh proses bekas dimiliki oleh root dan tidak boleh ditulis oleh pengguna hos anda.

Cara mengesahkan:

  1. Semak kebenaran fail dari hos:

    ls -l
    
    ls -l storage bootstrap/cache
    
    docker compose exec app id -u   # user id inside container
  2. Periksa log bekas untuk kesalahan kebenaran.

Pembaikan:

  • Pastikan Dockerfile menetapkan pengguna dan UID yang sepadan dengan pengguna hos anda (Dockerfile anda sudah mencipta pengguna dengan ARG uid). Sahkan uid dalam argumen binaan docker-compose.yml sepadan dengan UID hos anda (biasanya 1000).

  • Betulkan pemilikan dari hos atau dalam bekas:

    docker compose exec app chown -R sammy:sammy /var/www/storage /var/www/bootstrap/cache

    atau dari hos:

    sudo chown -R $(id -u):$(id -g) storage bootstrap/cache
  • Untuk pembangunan, pemasangan bind boleh menyebabkan ketidakpadanan kebenaran; sebaiknya jalankan arahan kontena untuk menyesuaikan pemilikan selepas membawa kontena ke atas.

Ralat berkaitan komposer atau pembekal

Gejala:

  • composer install gagal di dalam app atau folder vendor yang hilang menyebabkan kelas tidak dijumpai.
  • composer melaporkan penggunaan memori melebihi had dalam bekas.

Cara mengesahkan:

  • Jalankan composer di dalam kontena app dan tangkap output:

    docker compose exec app composer install --no-interaction --prefer-dist

Pembaikan:

  • Jika had memori composer dicapai, benarkan lebih banyak memori atau tetapkan pemboleh ubah persekitaran composer:

    docker compose exec app php -d memory_limit=-1 /usr/bin/composer install
  • Pastikan fail boleh laksana Composer ada (Dockerfile anda menyalin composer). Jika tidak, bina semula imej dengan lapisan composer.

  • Jika vendor tiada kerana overlay bind mount, pastikan bind mount anda tidak menyembunyikan folder vendor yang dibuat dalam imej. Amalan terbaik adalah menjalankan composer install selepas kontena dijalankan supaya vendor dibuat dalam folder yang dipasang, atau tambah vendor ke dalam kontena melalui pembinaan imej untuk produksi.

Aplikasi memaparkan halaman kosong atau ralat 500

Gejala:

  • Pelayar menunjukkan respon kosong atau HTTP 500.
  • Log Nginx menunjukkan 200 tetapi halaman kosong; log app menunjukkan pengecualian fatal.

Cara mengesahkan:

  • Periksa log aplikasi:

    docker compose exec app tail -n 200 storage/logs/laravel.log
    
    docker compose logs app --tail=200
  • Periksa persekitaran: APP_DEBUG=true dalam .env akan membuat Laravel menunjukkan ralat terperinci semasa pembangunan (jangan aktifkan dalam pengeluaran).

Pembaikan:

  • Perbaiki pengecualian asas yang ditunjukkan di laravel.log.

  • Pastikan .env wujud dan APP_KEY telah ditetapkan:

    docker compose exec app php artisan key:generate
  • Jalankan migrasi, bersihkan cache:

    docker compose exec app php artisan migrate --force
    
    docker compose exec app php artisan config:cache
    
    docker compose exec app php artisan route:cache
    
    docker compose exec app php artisan view:cache

Kegagalan bina kontena (ralat semasa docker compose build)

Gejala:

  • docker compose build gagal dengan ralat apt atau kegagalan langkah binaan.

Cara mengesahkan:

  • Jalankan semula binaan dengan log:

    docker compose build app

Pembaikan:

  • Baca output langkah yang gagal. Masalah biasa:

    • Rangkaian/DNS dalam persekitaran binaan: cuba semula atau pastikan Docker boleh mengakses internet.
    • Pakej hilang atau sumber apt salah: tambah apt-get update sebelum pemasangan dan bersihkan senarai apt selepas itu.
    • Kebenaran pada fail yang disalin ke dalam imej: pastikan laluan COPY betul.

Contoh petikan Dockerfile untuk pemasangan yang mantap:

RUN apt-get update && apt-get install -y --no-install-recommends \
    libpng-dev libxml2-dev zip unzip \
  && docker-php-ext-install pdo_mysql mbstring xml gd \
  && apt-get clean && rm -rf /var/lib/apt/lists/*

Masalah rangkaian atau DNS antara bekas

Gejala:

  • Satu kontena tidak dapat mencapai kontena lain melalui nama perkhidmatan (contohnya, app tidak dapat mencapai db dengan db:3306).
  • ping menggunakan nama perkhidmatan gagal.

Cara mengesahkan:

docker compose exec app ping -c 3 db

docker compose exec app getent hosts db

docker network inspect travellist

Pembaikan:

  • Sahkan perkhidmatan berkongsi rangkaian yang sama dalam docker-compose.yml (kedua-duanya harus merujuk kepada travellist).

  • Jika anda menukar nama perkhidmatan atau nama rangkaian, kemas kini DB_HOST dan Nginx upstreams dengan sewajarnya.

  • Bina semula rangkaian (ini akan memusnahkan bekas sementara, jadi berhati-hati):

    docker compose down
    
    docker network prune   # optional and destructive
    
    docker compose up -d

Arahan diagnostik yang berguna

Jalankan ini untuk pemeriksaan sasaran:

  • Tunjukkan kontena dan port yang sedang berjalan:

    docker compose ps
  • Log ekor untuk sesuatu perkhidmatan:

    docker compose logs -f --tail=200 nginx
  • Jalankan shell di dalam kontena:

    docker compose exec app sh
    
    docker compose exec db bash
  • Periksa pembolehubah persekitaran kontena:

    docker compose exec app env | sort
    
    docker compose exec db env | grep MYSQL
  • Semak senarai proses bekas:

    docker compose exec app ps aux
    
    docker compose exec app ss -ltnp
  • Periksa kesihatan MySQL:

    docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping

Bila hendak mendedahkan port hos untuk debugging

Secara lalai, perkhidmatan db dalam susunan ini tidak diikat pada port hos. Dedahkan port hanya untuk penyahpepijatan tempatan. Untuk mendedahkan MySQL sementara pada hos, tambah pada docker-compose.yml di bawah db:

ports:
  - "3306:3306"

Kemudian mulakan semula:

docker compose up -d db

Selepas debug, alihkan pemetaan ports untuk mengelakkan pengeksposan DB ke rangkaian.

Soalan Lazim

1. Adakah saya perlu memasang Composer di hos?

Tidak. Anda boleh menjalankan Composer sepenuhnya di dalam bekas aplikasi, yang merupakan pendekatan yang disyorkan untuk aliran kerja Compose ini. Dockerfile dalam tutorial ini termasuk Composer, jadi jalankan arahan seperti docker compose exec app composer install atau docker compose run --rm app composer require vendor/package. Menjalankan Composer di dalam bekas memastikan versi PHP dan sambungan yang betul digunakan dan mengelakkan penghasilan fail vendor dengan pemilikan yang tidak sepadan pada hos.

2. Bolehkah saya menjalankan migrasi Laravel dari dalam bekas?

Ya. Jalankan migrasi dari bekas aplikasi supaya ia menggunakan masa jalan dan rangkaian yang sama seperti aplikasi anda: docker compose exec app php artisan migrate. Untuk tugas sekali sahaja atau CI, anda boleh menggunakan docker compose run --rm app php artisan migrate --force. Sebelum menjalankan migrasi, pastikan bekas pangkalan data sihat dan menerima sambungan, contohnya dengan docker compose exec db mysqladmin -u$ {DB_USERNAME} -p$ {DB_PASSWORD} ping atau dengan mencuba semula sehingga ia memberi jawapan.

3. Bagaimana saya memasang sambungan PHP tambahan?

Tambahkan pakej sistem dan arahan sambungan yang diperlukan ke Dockerfile, kemudian bina semula imej tersebut. Contohnya, pasang kebergantungan dan bina sambungan biasa dengan sesuatu seperti:

RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev \
  && docker-php-ext-configure gd --with-jpeg \
  && docker-php-ext-install pdo_mysql mbstring gd

Jika anda memerlukan sambungan PECL, gunakan pecl install dan docker-php-ext-enable. Selepas mengedit Dockerfile, jalankan docker compose build app dan kemudian docker compose up -d app untuk menerapkan perubahan tersebut.

4. Bagaimana saya mendedahkan kontena Nginx untuk HTTPS?

Tambah blok pelayan HTTPS ke konfigurasi Nginx anda, pasang sijil dan kunci anda ke dalam kontena, dan publikasikan port 443 dalam docker-compose. Berikut adalah contoh dengan perubahan minimum dalam docker-compose.yml:

services:
  nginx:
    ports:
      - "8000:80"
      - "443:443"
    volumes:
      - ./docker-compose/nginx:/etc/nginx/conf.d
      - ./certs:/etc/nginx/certs:ro

Kemudian tambahkan blok pelayan SSL yang merujuk kepada /etc/nginx/certs/fullchain.pem dan /etc/nginx/certs/privkey.pem. Untuk pengeluaran, gunakan proksi terbalik atau pengurus sijil seperti Traefik atau penyeimbang beban luaran untuk mendapatkan dan memperbaharui sijil dengan selamat daripada menyimpan kunci peribadi dalam tumpukan aplikasi.

5. Bagaimana saya membina semula Laravel selepas membuat perubahan pada kod?

Ia bergantung kepada apa yang berubah. Jika anda menggunakan bind mounts untuk direktori projek, perubahan pada PHP, templat, laluan dan pengawal akan dipaparkan serta-merta; jalankan pembersihan cache Laravel jika perlu, contohnya:

docker compose exec app php artisan config:clear

docker compose exec app php artisan route:clear

docker compose exec app php artisan view:clear

Jika anda menukar kebergantungan composer atau Dockerfile (sambungan baru atau pakej sistem), pasang semula atau bina semula: docker compose exec app composer install untuk perubahan kebergantungan, dan docker compose build app && docker compose up -d untuk perubahan Dockerfile. Mulakan semula perkhidmatan yang terjejas apabila anda menukar konfigurasi PHP-FPM atau Nginx: docker compose restart app atau docker compose restart nginx.

Kesimpulan

Dalam panduan ini, kami telah menyediakan persekitaran Docker dengan tiga kontena menggunakan Docker Compose untuk mentakrifkan infrastruktur kami dalam fail YAML.

Mulai dari titik ini, anda boleh bekerja pada aplikasi Laravel anda tanpa perlu memasang dan menyediakan pelayan web tempatan untuk pembangunan dan ujian. Selain itu, anda akan bekerja dalam persekitaran yang boleh dibuang yang mudah ditiru dan diedarkan, yang boleh membantu semasa membangunkan aplikasi anda dan juga apabila beralih ke persekitaran pengeluaran.

Untuk lebih banyak tutorial Laravel, sila lihat artikel-artikel berikut:

  • Hoskan aplikasi Laravel anda di Linux-Console.net
  • Cara Memasang dan Mengkonfigurasi Laravel dengan Nginx pada Ubuntu (Pakej LEMP)
  • Cara Membuat Sumber API Eloquent Laravel untuk Menukar Model ke JSON
  • Cara Memulakan Aplikasi Laravel Baharu dengan Docker Compose

Terima kasih kerana belajar bersama Komuniti Linux-Console.net.