라라벨 도커 컴포즈 스택
이제 Docker Compose를 사용하여 프로덕션 환경을 로컬 환경으로 확장하고 Compose를 통해 사용할 수 있는 xdebug, linter 및 정적 분석 도구를 갖는 것과 같은 몇 가지 개발 편의성을 갖는 방법을 공유하고 싶습니다.
스택을 합성하는 서비스의 경우 app, mysql 및 redis가 있습니다. 각 서비스는 특정 Docker 이미지를 사용하고 앱 서비스는 이전에 빌드된 이미지를 사용하는 반면 mysql 및 redis는 Docker Hub에서 해당 이미지를 찾습니다.
콘텐츠
Services
App service
MySQL service
Redis service
도커 작성
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!
Reference
이 문제에 관하여(라라벨 도커 컴포즈 스택), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/jackmiras/docker-compose-for-a-laravel-app-ie7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)