Search code examples
phpdockerdocker-composelamp

Using Docker for multiple php applications


I recently moved from Wamp (wampserver) to Docker (Windows host). While using wamp, I was able to have multiple projects like in following file structure

- wamp64
  - www/
    - project1/ 
    - project2/
    - ....

On the wamp's Apache, I had defined a couple of virtual hosts, and all of the projects, used wamp's database, each one each own schema.

So it was quite common within the day to switch context when necessary from project1, to project2 to project3 etc.. by visiting either url like http://localhost/projectX or the corresponding virtual host.

This does not seem so straight forward on Docker, as I have seen so far. My first approach was to have a distinct Docker set up on each project

- www/
  - project1/
       - dockerfile & docker-compose
  - project2/
       - dockerfile & docker-compose
  - projectX/
       - dockerfile & docker-compose
- data // this is where mysql data lie

I think that this does not seem too efficient, compared to what I was used to using wamp, since every time I want to change context I have to use docker-compose stop the project I am currently working and docker-compose up to the project I want to switch to and vice versa.

I tried another approach, to run all projects in a single apache-php container (the entire www folder)

- www/
    dockerfile & docker-compose
    - project1/
    - project2/

which would let me have all projects available at once, but with this approach, I face two serious issues.

  1. docker build is taking too long, probably because of the increased number of files, instead of smaller amount on a single project
  2. i could not have more that one db schema initialized in mysql, so even though i managed to get 2 or 3 projects running, only 1 would be able to communicate with the corresponding db.

My docker-compose file in the first approach looks like this

version: '3'

services:

  project1:
    build:
      context: . // contents of specific project directory
      dockerfile: .docker/Dockerfile

    image: project1

    ports:
      – 80:80

    volumes:
      – .:/app/project1

   links:
      – mysql

  mysql:

    image: mysql:5.7

    ports:
      – 13306:3306

    environment:

      MYSQL_DATABASE: docker
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      MYSQL_ROOT_PASSWORD: docker

    volumes:
      - ../data:var/lib/mysql

while my docker-compose file in the second approach looks like this

version: '3'

services:

  web-project:
    build:
      context: . // contents of www directory
      dockerfile: .docker/Dockerfile

    image: web-project

    ports:
      – 80:80

    volumes:
      – /project1:/app/project1
      – /project2:/app/project2
      – /projectX:/app/projectX

   links:
      – mysql

  mysql:

    image: mysql:5.7

    ports:
      – 13306:3306

    volumes:
      - /data:var/lib/mysql

ref for mysql data persist Docker-Compose persistent data MySQL


Solution

  • I think the best solution for you would be to run each project in it's own container. Since containers are (should be) lightweight and easy to bring up and down, the overhead of doing this should be minimal.

    The difference in what I will show versus first approach is that the docker-compose file is going to orchestrate your containers for you. As a result it should allow all of your containers (projects) to communicate with your database at the same time. (Given your projects do not overwrite each-other constantly, and cause deadlock)

    Folder Structure:

    - www/
        docker-compose.yml
        - project1/
          Dockerfile
        - project2/
          Dockerfile
    

    Docker Compose

    version: '3'
    services:
      project1:
        build:
          context: /project1 #automatically finds Dockerfile
        container_name: project1
        ports:
          – 8081:80
        volumes:
          – .:/app/project
       links:
          – mysql
      project2:
        build:
          context: /project2 #automatically finds Dockerfile
        container_name: project2
        ports:
          – 8082:80
        volumes:
          – .:/app/project
       links:
          – mysql
      ...
      mysql:
        image: mysql:5.7
        ports:
          – 13306:3306
        volumes:
          - /data:var/lib/mysql
    

    Then when you run docker-compose up it will bring up two project containers and a database containers within the same network. Note that each project is run on it's own port. So you will need to remember which port is linked to which container.