In Action Tutorial Series - Docker - PHP Development with Docker
Bài đăng này đã không được cập nhật trong 7 năm
A. Getting started
A.1. Brief explanation
A.1.1. Image
Image is a package which includes code, a runtime, libraries, environment variables, and config files (Dockerfile). Get from http://hub.docker.com Types:
- By source: offical and public/user image
- By level: scratch, base os and application image
A.1.2. Container
Container is a running instance of a image. It is isolated from host env, only accessing host files and ports if configured
A.1.3. Docker compose
Docker compose is a tool for managing many docker container in a central config file (docker-compose.yml)
A.2. Installing
Install docker
To install AUFS storage driver. Others drivers: Btrts, Device mapper, VFS, ZFS
$ apt-get install \
linux-image-extra-$(uname -r) \
linux-image-extra-virtual
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
Add docker repository
$ add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
Install docker ce
$ apt-get install docker-ce
Check
$ docker -v
// Docker version 17.03.1-ce, build c6d412e
Install docker-compose
Get binary
$ curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
Move to bin folder
$ sudo mv ~/docker-compose /usr/local/bin/docker-compose
Make it executable
$ sudo chmod +x /usr/local/bin/docker-compose
Check
$ docker-compose --version
$ #docker-compose version 1.13.0, build 1719ceb
First hello world application
Create helloworld folder
mkdir ~/test && cd ~/test
Create example index.php file
echo "<?php echo 'Welcome to docker'; ?>" > index.php
Create Dockerfile
touch Dockerfile
Add following lines to Dockerfile
# Set base application image.
FROM php:7.0-cli
# Set working dir in container environment
WORKDIR /app
# Add all current files and folder on host env to container env
ADD . /app
# Alternative: COPY . /app
# Run command `php index.php` in container env
CMD ["php", "index.php"]
# Alternative: CMD php index.php
Build up image
docker build -t helloworld ./
# -t helloworld: set helloworld as image name
# ./ : context to build image. ./ mean current directory
Running container use helloworld image
docker run helloword
If you see "Welcome to docker" you're ready to go
B. Basic usage cases
There are 3 ways to up and run a php application with docker. From hardest-low abstraction level
to easiest-high abstraction level
. I suggest to flow this order to understand more deeply and less confusing with last way.
Let's dig into!
B.1. Up and running php application without docker-compose
Assume ~/project is project root folder
Step 1: Create 3 custom images with nginx, php-fpm, mysql
First create our docker folders
cd ~/project/docker && mkdir php-fpm mysql nginx
NOTE: Because limit folder access. So the context must be project root folder. Create php-fpm/Dockerfile with following lines
FROM php:fpm
# Project root context so we use .
ADD . /code
WORKDIR /code
CMD ["php-fpm"]
# Expose port for other services can use
EXPOSE 9000
Create nginx/Dockerfile with following lines
FROM nginx:alpine
WORKDIR /code
# Add our default site config
ADD ./docker/nginx/site.conf /etc/nginx/conf.d/
# Remove default nginx site
RUN rm /etc/nginx/conf.d/default.conf
CMD ["nginx"]
# Expose port for other services can use
EXPOSE 80 443
Create nginx/site.conf with content
server {
listen 80 default_server;
server_name localhost;
root /code;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri /index.php =404;
// Some magical here :D. I'll explain later
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
With mysql we dont need other configurations so we use base official mysql image is enough. We just start container use it in step 4
Step 2: Create network
Each container must in a same network to communicate with each others. So we create network
$ docker network create mynetwork
default use bridge driver. You can change it by using option --driver=<driver_name>
Step 3: Create share volume
We must define a volume which share code folder for nginx serve static content and php-fpm compile PHP script
$ docker volume create myvolume
Step 4: Startup 3 containers with share volume and joining network
docker run -v myvolume:/code --net mynetwork --name php-fpm php-fpm
docker run -v myvolume:/code --net mynetwork -p 8888:80 nginx
docker run --net mynetwork --name mysql mysql:latest
IMPORTANT NOTES:
- Because containers are isolated from other so you must join containers into same network. Same as volume
- p 8888:80 means forward port 80 in nginx container to port 8888 on host environment
- Define --name argument give us 2 benefits
- Manage container easily with name instead of long ID
- Docker uses these names to find the IP of the services and containers for you. You can use hostnames in your code to provide abstraction that allows you to easily swap service containers or components. So you don't need/shouldn't to define static other service ip. Example is in nginx configuration above.
Test on: localhost:8888. You're up and runing. Cheer! But this is so long and has many boring repitive tasks. So docker-compose is here and save us
B.2. Up and running php application with docker-compose
All we need is a nginx configuration file and docker-compose.yml file
Step 1: Create nginx configuration file
First create new folder
mkdir ~/project/docker-compose && cd ~/project/docker-compose
Create site.conf with flowing content
server {
listen 80 default_server;
server_name localhost;
root /code;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri /index.php =404;
// Some magical here :D. I has explained..
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Step 2: Create docker-compose.yml
Create docker-compose.yml with content
version: '2'
services:
php:
image: php:fpm
volumes:
- ..:/code
networks:
- mynetwork
web:
image: nginx:latest
ports:
- "8000:80"
volumes:
- ..:/code
- ./site.conf:/etc/nginx/conf.d/default.conf
networks:
- mynetwork
mysql:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=root
networks:
- mynetwork
networks:
mynetwork:
driver: bridge
Run docker-composer up and hurra! you get the same result as B.1. But this way is more clear and less painful. Right?
B.3. Up and running php application with laradock
Laradock is a full PHP development environment for Docker. If 2 ways above still make you uncomfortable or you want a more speedy way. Laradock is for you.
Step 1: Setup main laradock
Clone Laradock to anywhere you want. I assume ~/laradock
$ git clone https://github.com/Laradock/laradock.git ~/laradock
Enter the laradock folder and rename env-example
to.env
$ cp ~/laradock/env-example ~/laradock/.env
Modify variable APPLICATION
in ~/laradock/.env
to folder contains all your projects. Assuming ~/code
APPLICATION=/home/user/code/
According to ~/laradock/docker-compose.yml
. All folders and files in /home/user/code/
host env will be added to /var/www
in container env
Step 2: Setup sites
Open ~/laradock/nginx/sites folder. There has 2 example site configs. You can create many sites as you want. Just copy example and change server_name
, root
variables which are suitable for each project
Edit /etc/hosts on host env
127.0.0.1 localhost project1.dev project2.dev project3.dev
Inside laradock. Run
docker-compose up mysql nginx -d
# -d mean detach. You run docker in background mode
Test on project1.dev,..etc. That's it!
C. Appendices
C.1. Docker useful commands
C.1.1. docker image
- List all image
docker image ls
- Remove a image
docker image rm <image_id>
- Build a image
docker image build <context>
- View info about a image
docker image info <image_id>
C.1.2. docker container
- Run a container from a local image or "on the cloud" image
docker run [-d] [--net <network_name>] [-v <volume_name>:<mount_path>] [--name <wanted_container_name>] <image_id>
- -d for detach mode
- List container
docker container ps [-a]
- -a for including not running container
- Remove a container
docker container rm <container_id>
- Stop, pause, start, restart container
docker container stop | start | pause | restart <container_id>
- Exec a command in container
docker container exec <container_id> <command>
- Use bash inside container
docker container exec -it <container_id> /bin/bash
C.1.3. docker volume
- List all volumes
docker volume ls
- Remove a volume
docker volume rm <volume_name>
- Create a volume
docker volume create <volume_name> [-driver <driver_name>]
- Inspect a volume
docker volume inspect <volume_name>
C.1.3. docker network
- List all networks
docker network ls
- Remove a network
docker network rm <network_name>
- Create a network
docker network create <network_name> [-driver <driver_name>]
- Inspect a network
docker network inspect <network_name>
- Connect/disconnect a container to/from a network
docker network connect | disconnect <network_name> <container_id>
C.2. Docker-compose useful commands
- Start all services
docker-compose up [-d]
- Start specific containers
docker-compose up [-d] <service_1> <service_2> ...
- Stop all services
docker-compose down
- List all containers running
docker-compose images
- Use bash inside container
docker-compose exec <service_name> /bin/bash
Thanks for reading!
Source:
All rights reserved