라라벨 도커 컴포즈 스택

36438 단어 phpalpinedockerlaravel
지난 번 출판에서 저는 프로덕션 환경을 위해 Laravel Docker 이미지를 빌드하는 것을 선호하는 방법에 대해 이야기했습니다.

이제 Docker Compose를 사용하여 프로덕션 환경을 로컬 환경으로 확장하고 Compose를 통해 사용할 수 있는 xdebug, linter 및 정적 분석 도구를 갖는 것과 같은 몇 가지 개발 편의성을 갖는 방법을 공유하고 싶습니다.

스택을 합성하는 서비스의 경우 app, mysql 및 redis가 있습니다. 각 서비스는 특정 Docker 이미지를 사용하고 앱 서비스는 이전에 빌드된 이미지를 사용하는 반면 mysql 및 redis는 Docker Hub에서 해당 이미지를 찾습니다.

콘텐츠


  • Docker Compose
  • Version

  • Services

  • App service
  • Directive build
  • Directive container_name
  • Directive command
  • Directive ports
  • Directive env_file
  • Directive volumes
  • Directive networks


  • MySQL service
  • Directive image
  • Directive container_name
  • Directive ports
  • Directive volumes
  • Directive environment
  • Directive networks
  • Connecting Laravel to MySQL


  • Redis service
  • Directive image
  • Directive container_name
  • Directive ports
  • Directive volumes
  • Directive networks
  • Connecting Laravel to Redis


  • Volumes
  • Networks

  • 도커 작성

    Down below, there is an entire docker-compose.yml, read it carefully, YAML files strongly rely on indentation and its directives depend entirely on the interpreter.

    A good part of the directives will be explained further, but if you want to know every bit of this file, check the compose file reference 문서.

    version: "3"
    services:
      app:
        build: .
        container_name: laravel_scaffold
        command: >-
          sh -c "
            apk add php8-pecl-xdebug && composer install ;\
            cp .docker/php.ini-development /etc/php8/php.ini ;\
            cp .docker/xdebug.ini /etc/php8/conf.d/50_xdebug.ini ;\
            php artisan serve --host 0.0.0.0 --port 80"
        ports:
          - "8000:80"
        env_file:
          - .env
        volumes:
          - .:/var/www/html:rw
        networks:
          - app_network
    
      mysql:
        image: mysql:8
        container_name: laravel_scaffold_db
        ports:
          - "3306:3306"
        restart: "no"
        volumes:
          - db_data:/var/lib/mysql
        environment:
          - MYSQL_DATABASE=homestead
          - MYSQL_USER=homestead
          - MYSQL_PASSWORD=secret
          - MYSQL_ROOT_PASSWORD=secret
        networks:
          - app_network
    
      redis:
        image: redis:alpine
        container_name: laravel_scaffold_cache
        ports:
          - "6379:6379"
        volumes:
          - cache_data:/data
        networks:
          - app_network
    
    volumes:
      db_data:
        driver: "local"
      cache_data:
        driver: "local"
    
    networks:
      app_network:
        driver: "bridge"
    
    


    버전

    The first step towards the construction of a docker-compose.yml is to define the version of the file format.

    version: "3"
    

    The file format version is directly related to the Docker releases, which means that this version may change according to the version of the Docker engine running on your computer.

    서비스

    Services are a set of configurations that are applied to each container at the starting of that service, much like passing command-line parameters to docker run. To let Compose know that the definition of services is happening, you need to place the directive services: , right after the line defining the Version, as the docker-compose up above shows.

    앱 서비스

    As mentioned before, the services are app, mysql, and redis, let's dive into the app service since this service holds some interactions with the container previously built, using the Dockerfile from the last publishing.

    app:
      build: .
      container_name: laravel_scaffold
      command: >-
        sh -c "
          apk add php8-pecl-xdebug && composer install ;\
          cp .docker/xdebug.ini /etc/php8/conf.d/50_xdebug.ini ;\
          php artisan serve --host 0.0.0.0 --port 80"
      ports:
        - "8000:80"
      env_file:
        - .env
      volumes:
        - .docker/xdebug.ini
        - .:/var/www/html:rw
      networks:
        - app_network
    

    As the code shows app: is both a directive and the name definition for the service, under this service definition we have seven configurations directives, build, container_name, command, ports, env_file, volumes, and networks.


    Directive build
    build: .
    

    It tells Compose that we want to build a container when this service specification gets processed, while the . after the directive tells Compose that the container must be built from the Dockerfile that is relative to the docker-compose.yml.

    Remember, they have to be in the same directory, otherwise, you have to specify the path to the Dockerfile. A suggestion is to keep both the Dockerfile and docker-compose.yml at the root of the Laravel projects.


    Directive container_name
    container_name: laravel_scaffold
    

    Its specifies a custom container name, rather than a generated default one, it works for built or pulled containers, and makes it easier to identify containers from specific docker-compose stacks. In this case, it's saying that the container behind the app service should be named laravel_scaffold.

    A good naming convention around container_name will help you find and manage containers easily, especially if you have a few docker-compose.yml files. This can easily grow to dozens of containers and having standardized names will help you know if a Redis container is from a Laravel or an Express.js stack.


    Directive command
    command: >-
      sh -c "
        apk add php8-pecl-xdebug && composer install ;\
        cp .docker/php.ini-development /etc/php8/php.ini ;\
        cp .docker/xdebug.ini /etc/php8/conf.d/50_xdebug.ini ;\
        php artisan serve --host 0.0.0.0 --port 80"
    

    It's used to override the default command from the Dockerfile in use, looking at the first line we can see that xdebug and composer with all dependencies got installed.

    At the second line , the php.ini-development file gets copied from a local .docker folder into /etc/php8/php.ini at the container. This file contains all the configurations that PHP will run upon, the content of this file got copied from PHP's official repository on GitHub .

    세 번째 줄에서 xdebug.ini 파일은 로컬 .docker 폴더에서 컨테이너의/etc/php8/conf.d/50_xdebug.ini로 복사됩니다. 이 파일에는 호스트인 컴퓨터가 컨테이너에 연결하고 xdebug를 사용할 수 있도록 하는 구성이 포함되어 있습니다. xdebug 구성은 다음과 같습니다.

    zend_extension=xdebug.so
    xdebug.mode=develop,coverage,debug,profile
    xdebug.idekey=docker
    xdebug.remote_handler=dbgp
    xdebug.start_with_request=yes
    xdebug.log=/dev/stdout
    xdebug.log_level=0
    xdebug.client_port=9003
    xdebug.client_host=<YOUR_COMPUTER_IP>
    


    마지막으로 Laravel의 표준 서버는 장인 명령줄 인터페이스를 사용하여 시작되었습니다. Dockerfile 명령을 재정의했으므로 애플리케이션을 제공하려면 서버를 시작해야 합니다.

    This approach may seem odd at first, but this is what makes it possible to have a Dockerfile with production definitions only. Installing xdebug will allow any person working in the project to use a full-featured debug, while the installation of all composer dependencies allows the person to use hooks, linters, static analysis tools, or any other development tool in a containerized environment.

    It is helpful because avoids the situation of people having to set up a development environment in their computers, with this approach they just need to run the Compose stack while the DevOps team can just build the Dockerfile and deploy it.




    Directive ports
    ports:
      - "8000:80"
    

    It exposes ports in the format of HOST:CONTAINER; hence the directive is mapping the port 8000 from the host to port 80 of the container.

    The host port of choice is arbitrary, any available port can be used, while the container port has to match the port used to serve the application, as the third line of the command directive shows, that port is port 80.

    Then, to access the application from postman, insomnia, or browser you just need to use http://localhost:8000 .


    Directive env_file
    env_file:
      - .env
    

    Add environment variables from a file, it can be a single value or a list. Hence, the directive is loading the .env file that is relative to the docker-compose.yml.


    Directive volumes
    volumes:
      - .docker/xdebug.ini
      - .:/var/www/html:rw
    

    It maps files or directories, in the format SOURCE:TARGET[:MODE]. This syntax can be used to ignored or sync volumes between the host and the container and specify modes or permissions to the volumes mapped.

    In the first line, we are specifying a SOURCE volume without TARGET or MODE, this syntax will ignore the file .docker/xdebug.ini. The file got ignored because we already copied him to the /etc/php8/conf.d/50_xdebug.ini at the command directive and there is no need to copy him again.

    In the second line, we are syncing the directory where the docker-compose.yml is, into the /var/www/html of the container with reading and write permission. As mentioned, the docker-compose.yml is usually at the root of my Laravel projects, this means that the entire project got synced.

    The second line of the volumes mapping is the approach that allows live reloading in the project, in this way you don't need to stop the container and spin them up again after changing something in the text editor or IDE. Since the volumes (directories and files) are synced any change made in the host will reflect in the container and vice versa.


    Directive networks
    networks:
      - app_network
    

    It specifies networks to join, referencing entries under the top-level networks key. The app_network will be defined and explained further in this article.

    MySQL 서비스

    mysql:
      image: mysql:8
      container_name: laravel_scaffold_db
      ports:
        - "3306:3306"
      volumes:
        - db_data:/var/lib/mysql
      environment:
        - MYSQL_DATABASE=homestead
        - MYSQL_USER=homestead
        - MYSQL_PASSWORD=secret
        - MYSQL_ROOT_PASSWORD=secret
      networks:
        - app_network
    

    As mentioned before, mysql: is both a directive and the name definition for the service, under this service definition we have six configurations directives, image, container_name, ports, environment, and networks.


    Directive image
    image: mysql:8
    

    Specify the image to start the container from, usually a repository with a tag, bear in mind that if the tag is not present, the Docker engine will look for the repository plus the latest tag. In case the image does not exist, Compose attempts to pull it, usually from Docker Hub, unless you have also specified build, in which case it builds it using the specified options and tags it with the specified tag.

    In case you have a custom registry configured, such as AWS ECR, the Docker engine will look into ECR and try to find an image mysql with tag 8 and only if an image cannot be found in ECR that it will fall back to Docker Hub, so be careful with your image's naming convention.


    Directive container_name
    container_name: laravel_scaffold_db
    

    Its specifies a custom container name, rather than a generated default one, it works for built or pulled containers. In this case, it's defining the container name behind the mysql service as laravel_scaffold_db.


    Directive ports
    ports:
      - "3306:3306"
    

    The directive is mapping the port 3306 from the host to port 3306 of the container. To access the application from MySQL Workbench, DBeaver, or DataGrip you just need to use localhost as host at port 3306.


    Directive volumes
    volumes:
      - db_data:/var/lib/mysql
    

    Here, we are using db_data: as a named volume in the top-level volumes key. The definition of the volume will be explained further, but basically Compose gets instructed to create a db_data directory at /var/lib/docker/volumes.

    Since /var/lib/docker/volumes/db_data is being created the result of the volume mounting is that everything crated by MySQL at /var/lib/mysql will be synced to the db_data directory, this includes the databases and the data stored in them.


    Directive environment
    environment:
      - MYSQL_DATABASE=homestead
      - MYSQL_USER=homestead
      - MYSQL_PASSWORD=secret
      - MYSQL_ROOT_PASSWORD=secret
    

    Defines environment variables to the container, here we are defining MySQL variables that define the default database, user, password and root password. Note that the environment variables follows the same patter that the .env file present at the Laravel project that we loaded at the app service using the env_file directive.


    Directive networks
    networks:
      - app_network
    

    It specifies networks to join, referencing entries under the top-level networks key. The app_network will be defined and explained further in this article.


    Connecting Laravel to MySQL

    With app service defined and Laravel application ready to run, we need to update Laravel's .env file, to connect to this MySQL service. For that, it's necessary to change the environment variable DB_HOST=127.0.0.1 to DB_HOST=mysql.

    As you may have notice, we are using the service name mysql as host, that is because Docker resolves the service name into a network connection and further into and IP address that can be used between app and mysql services containers.

    레디스 서비스

    redis:
      image: redis:alpine
      container_name: laravel_scaffold_cache
      ports:
        - "6379:6379"
      volumes:
        - cache_data:/data
      networks:
        - app_network
    

    As mentioned before, redis: is both a directive and the name definition for the service, under this service definition we have five configurations directives, image, container_name, ports, environment, and networks.


    Directive image
    image: redis:alpine
    

    As mentioned, this directive specifies the image to start the container from a repository, and in case the image does not exist, Compose will attempt to pull it from Docker Hub.


    Directive container_name
    container_name: laravel_scaffold_cache
    

    Its specifies a custom container name, rather than a generated default one, it works for built or pulled containers. In this case, it's defining the container name behind the redis service as laravel_scaffold_cache.


    Directive ports
    ports:
      - "6379:6379"
    

    The directive is mapping the port 6379 from the host to port 3306 of the container. To access the application from RedisInsight, or RDM (Redis Desktop Manager) you just need to use localhost as host at port 6379.


    Directive volumes
    volumes:
      - cache_data:/data
    

    Here, we are using cache_data: as a named volume in the top-level volumes key. The definition of the volume will be explained further, but basically, Compose gets instructed to create a cache_data directory at /var/lib/docker/volumes.

    Since /var/lib/docker/volumes/cache_data is being created the result of the volume mounting is that everything crated by Redis at /data will be synced to the cache_data directory, this includes the databases and the hashes stored in them.


    Directive networks
    networks:
      - app_network
    

    It specifies networks to join, referencing entries under the top-level networks key. The app_network will be defined and explained further in this article.


    Connecting Laravel to Redis

    To connect into the Redis service, we need to update Laravel's .env file, changing the environment variable from REDIS_HOST=127.0.0.1 to REDIS_HOST=redis. As mentioned, we have to use the service name as host, so Docker can resolve the service name into a network connection that can be used between app and redis services containers.

    볼륨

    volumes:
      db_data:
        driver: "local"
      cache_data:
        driver: "local"
    

    Here we have what Compose defines as top-level volumes, these volumes gets defined outside the services. This approach used when high level of reusage is need or if volumes has a lifecycle that differs from the service.

    For both volumes, we are defining named volumes db_data: , and cache_data: . Similar to the service these are directives and name definitions, the volumes definitions have also the directive driver: set to local , this means that this volume will be attached to the host disk.

    Since the driver is local, the result will be a /var/lib/docker/volumes/db_data and /var/lib/docker/volumes/cache_data directories getting created. After attaching this volumes into a service, everything crated by the service will be synced to the previously created directories.

    Furthermore, the data at volumes will not be deleted when the service using the volume gets restarted, recreated or deleted, and this is a behavior that we want when using volumes with data persistent services, such as MySQL and Redis.

    네트워크

    networks:
      app_network:
        driver: "bridge"
    

    Here we are defining top-level networks, this network got defined outside the service, the network definition have also the directive driver: set to bridge , this means that services attached to this network get bridged to each other. This approach is what allows app service to connect into mysql and redis services without any special config.


    Now your docker-compose.yml is finally done, and you can build and run all the containers from it by executing docker-compose up in your terminal. To run the containers in the background hiding logs and outputs, you can do it by executing docker-compose up -d in your terminal.

    Happy coding!

    좋은 웹페이지 즐겨찾기