diff --git a/.docker/mysql/my.cnf b/.docker/mysql/my.cnf new file mode 100644 index 0000000..decfa40 --- /dev/null +++ b/.docker/mysql/my.cnf @@ -0,0 +1,3 @@ +[mysqld] +collation-server = utf8mb4_unicode_ci +character-set-server = utf8mb4 diff --git a/.docker/nginx/conf.d/php.conf b/.docker/nginx/conf.d/php.conf new file mode 100644 index 0000000..f4b5369 --- /dev/null +++ b/.docker/nginx/conf.d/php.conf @@ -0,0 +1,14 @@ +server { + listen 80; + listen [::]:80; + server_name php.test; + root /var/www/php; + index index.php; + + location ~* \.php$ { + fastcgi_pass php:9000; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + } +} diff --git a/php/Dockerfile b/.docker/php/Dockerfile similarity index 68% rename from php/Dockerfile rename to .docker/php/Dockerfile index dd05f2e..f9cfa68 100644 --- a/php/Dockerfile +++ b/.docker/php/Dockerfile @@ -1,3 +1,3 @@ -FROM php:7.0-fpm +FROM php:7.4-fpm RUN docker-php-ext-install pdo_mysql \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100755 index 0000000..c516ed7 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=demo diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/LICENSE b/LICENSE index 62717ef..4a71334 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 Yannick Chenot +Copyright (c) 2020 Yannick Chenot Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 393e27d..d0aae02 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,92 @@ -**[WARNING] This repository is deprecated and only maintained for legacy purposes. For an up to date Docker set up, please head over [here](https://github.com/osteel/docker-tutorial-2), thank you.** +# Docker for local web development, part 1: a basic LEMP stack -# Docker tutorial +This repository accompanies a [tutorial series](https://tech.osteel.me/posts/docker-for-local-web-development-why-should-you-care "Docker for local web development, introduction: why should you care?") about leveraging Docker for local web development. -This is the companion repository for [From Vagrant to Docker: How to use Docker for local web development](http://tech.osteel.me/posts/2015/12/18/from-vagrant-to-docker-how-to-use-docker-for-local-web-development.html "From Vagrant to Docker: How to use Docker for local web development"). Please refer to it for a full explanation. +The current branch covers part 1 of the series - please refer to the [full article](https://tech.osteel.me/posts/docker-for-local-web-development-part-1-a-basic-lemp-stack "Docker for local web development, part 1: a basic LEMP stack") for a detailed explanation. -It contains a basic LEMP stack running with Docker, intented to be used for local web development. +## Content -## Get started +This branch contains a basic LEMP stack running on Docker and orchestrated by Docker Compose, including: -[Install Docker](https://docs.docker.com/engine/installation/ "Install Docker Engine") on your machine. +* A container for Nginx; +* A container for PHP-FPM; +* A container for MySQL; +* A container for phpMyAdmin; +* A volume to persist MySQL data. -Clone the project: +## Prerequisites - $ git clone git@github.com:osteel/docker-tutorial.git +Make sure [Docker Desktop for Mac or PC](https://www.docker.com/products/docker-desktop) is installed and running, or head [over here](https://docs.docker.com/install/) if you are a Linux user. You will also need a terminal running [Git](https://git-scm.com/). -From the project root: +This setup also uses localhost's port 80, so make sure it is available. - $ docker-compose up -d +## Directions of use -Get the Docker Machine IP: +Add the following domain to your machine's `hosts` file: - $ docker-machine ip default +``` +127.0.0.1 php.test +``` -Access it from your browser. +Clone the repository and change the current directory for the project's root: -## Description +``` +$ git clone git@github.com:osteel/docker-tutorial.git +$ cd docker-tutorial +``` -The different containers are described in [`docker-compose.yml`](https://github.com/osteel/docker-tutorial/blob/master/docker-compose.yml). +Copy `.env.example` to `.env`: -There are 6 of them: +``` +$ cp .env.example .env +``` - - a container for Nginx - - a container for PHP-FPM - - a container for MySQL - - a container for phpMyAdmin - - a container to make MySQL data persistent - - a container for the application code +Run the following command: -All of them are using official images. +``` +$ docker-compose up -d +``` -When building and starting containers for the first time with Docker Compose, a database named `project` will be created by default. You can change this in [`docker-compose.yml`](https://github.com/osteel/docker-tutorial/blob/master/docker-compose.yml). +This may take a little bit of time, as some Docker images might need downloading. -A [default Nginx configuration](https://github.com/osteel/docker-tutorial/blob/master/nginx/default.conf) is also copied over. +Once the script is done, visit [php.test](http://php.test) (you might initially get a MySQL error message: this is because the database is still being created; the error will soon disappear upon refreshing the page). -The `www/html/` directory is mounted into the one served by Nginx on the container, so any update to the code is available without having to rebuild the container. +## Explanation -The MySQL data sits in its own directory mounted into its own container to make it persistent. +The images used by the setup are listed and configured in [`docker-compose.yml`](https://github.com/osteel/docker-tutorial/blob/part-1/docker-compose.yml). -The application is available on the port 80 of the host machine. +When building and starting the containers based off the images for the first time, a MySQL database named `demo` is automatically created (you can pick a different name in the MySQL service's description in `docker-compose.yml`). -phpMyAdmin is available on port 8080. +A [minimalist Nginx configuration](https://github.com/osteel/docker-tutorial/blob/part-1/.docker/nginx/conf.d/php.conf) for the PHP application is also copied over to Nginx's container, making it available at [php.test](http://php.test). -Again, for the complete tutorial please head to the [original post](http://tech.osteel.me/posts/2015/12/18/from-vagrant-to-docker-how-to-use-docker-for-local-web-development.html "From Vagrant to Docker: How to use Docker for local web development"). \ No newline at end of file +The `src/` directory containing the application is mounted onto both Nginx's and the application's containers, meaning any update to the code is immediately available upon refreshing the page, without having to rebuild any container. + +The database data is persisted in its own local directory through the volume `mysqldata`, which is mounted onto MySQL's container. A phpMyAdmin interface is available at [localhost:8080](http://localhost:8080). + +Please head over to the [full article](https://tech.osteel.me/posts/docker-for-local-web-development-part-1-a-basic-lemp-stack "Docker for local web development, part 1: a basic LEMP stack") for a detailed explanation. + +## Cleaning up + +To stop the containers: + +``` +$ docker-compose stop +``` + +To destroy the containers: + +``` +$ docker-compose down +``` + +To destroy the containers and the associated volumes: + +``` +$ docker-compose down -v +``` + +To remove everything, including the images: + +``` +$ docker-compose down -v --rmi all +``` diff --git a/docker-compose.yml b/docker-compose.yml index 54ac663..8d5e622 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,48 +1,49 @@ -nginx: - build: ./nginx/ - ports: - - 80:80 - links: - - php - volumes_from: - - app +version: '3.7' -php: - build: ./php/ - expose: - - 9000 - links: - - mysql - volumes_from: - - app +# Services +services: -app: - image: php:7.0-fpm + # Nginx Service + nginx: + image: nginx:1.17 + ports: + - 80:80 volumes: - - ./www/html:/var/www/html - command: "true" + - ./src:/var/www/php:ro + - ./.docker/nginx/conf.d:/etc/nginx/conf.d:ro + depends_on: + - php -mysql: - image: mysql:latest - volumes_from: - - data - environment: - MYSQL_ROOT_PASSWORD: secret - MYSQL_DATABASE: project - MYSQL_USER: project - MYSQL_PASSWORD: project + # PHP Service + php: + build: ./.docker/php + working_dir: /var/www/php + volumes: + - ./src:/var/www/php + depends_on: + - mysql -data: - image: mysql:latest + # MySQL Service + mysql: + image: mysql:8 + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: demo volumes: - - /var/lib/mysql - command: "true" + - ./.docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro + - mysqldata:/var/lib/mysql -phpmyadmin: - image: phpmyadmin/phpmyadmin + # PhpMyAdmin Service + phpmyadmin: + image: phpmyadmin/phpmyadmin:5 ports: - - 8080:80 - links: - - mysql + - 8080:80 environment: - PMA_HOST: mysql + PMA_HOST: mysql + depends_on: + - mysql + +# Volumes +volumes: + + mysqldata: diff --git a/nginx/Dockerfile b/nginx/Dockerfile deleted file mode 100644 index bf11540..0000000 --- a/nginx/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM nginx:latest - -COPY ./default.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/nginx/default.conf b/nginx/default.conf deleted file mode 100644 index ae4a5a3..0000000 --- a/nginx/default.conf +++ /dev/null @@ -1,36 +0,0 @@ -server { - listen 80 default_server; - root /var/www/html; - index index.html index.php; - - charset utf-8; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location = /favicon.ico { access_log off; log_not_found off; } - location = /robots.txt { access_log off; log_not_found off; } - - access_log off; - error_log /var/log/nginx/error.log error; - - sendfile off; - - client_max_body_size 100m; - - location ~ \.php$ { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass php:9000; - fastcgi_index index.php; - include fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_intercept_errors off; - fastcgi_buffer_size 16k; - fastcgi_buffers 4 16k; - } - - location ~ /\.ht { - deny all; - } -} \ No newline at end of file diff --git a/src/hello.gif b/src/hello.gif new file mode 100644 index 0000000..b3c7c43 Binary files /dev/null and b/src/hello.gif differ diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..ed171ed --- /dev/null +++ b/src/index.php @@ -0,0 +1,39 @@ + + + + + Hello there + + + + Hello there + query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'demo'"); + $tables = $query->fetchAll(PDO::FETCH_COLUMN); + + if (empty($tables)) { + echo '

There are no tables in database demo.

'; + } else { + echo '

Database demo contains the following tables:

'; + echo ''; + } + ?> + + \ No newline at end of file diff --git a/www/html/index.php b/www/html/index.php deleted file mode 100644 index 3a85fc6..0000000 --- a/www/html/index.php +++ /dev/null @@ -1,28 +0,0 @@ - - - - - Hello World! - - - Hello World! - query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_TYPE='BASE TABLE'"); - $tables = $query->fetchAll(PDO::FETCH_COLUMN); - - if (empty($tables)) { - echo "

There are no tables in database \"{$database}\".

"; - } else { - echo "

Database \"{$database}\" has the following tables:

"; - echo ""; - } - ?> - - \ No newline at end of file