Strategies for multiple instances deployment

Hi everyone,

I’m starting the development of a new app, that will run in an instance for each of my customers. Up to now, I’ve allways developed “one instance” apps, because those are taylor made for each customer. But this new one will be a standard product.

So, I’m thinking about how to automate the new instance setup:

  1. Create site in Apache
  2. Clone the GIT repository - Install dependencies with composer
  3. Create the database
  4. Associate the database to the instance
  5. Run migrations

After step 5, I should have the instance ready for first use.

Have anyone worked on something like this? If yes, what is the best approach?

Talking to a fellow PHP developer with no CakePHP background, he suggested using Docker.

Saludos,

Hi @dcoturel,

Yes docker is the way to go. Using docker you can have consistent configuration of your apache, php, mysql. So you don’t have to worry about managing the configuration and versions for each of them. You can specify the default skeleton cakephp app to fetch the project and then simply use CakePHP migrations to migrate the database structure.

You can find reference for docker with cakephp using below links:

Cheers!

Yes docker will make the project super portable. Try to use docker-compose to set it up and use an .env file to configure database, smtp, error reporting, etc.

I have a docker image that adds a simply run.sh that does:

  • Waits for mysql to be ready (if it does not connect in 30 seconds it fails, restarting the container)
  • Run migrations and plugins migrations
  • (Add extra steps like creating upload folder structure in docker volume)
  • run apache/nginx

that way when you want to deploy a new client. You have to copy only docker-compose.yml, the env file (configure it), call docker-compose up -d and you are ready.

When there is an update, simple make docker-compose pull, docker-compose up -d (assuming you setup your public/private docker registry).

You can setup other services like mariadb, redis, etc. in the same docker-compose file. If you have a cron, when you build the docker image with apache/nginx and cron. Set up as 2 identical services, but only one command: cron -f -l 8 for example.

Hi Bizdev, Raul, seems clear that Docker is the way to go then. I’ll research how it works, since I have never used it. I have one question, can you deploy multiple dockers in one server? Does it have a significative performance penalty?

Saludos,

There is very little to no performance penalties.

I suggest watch this video from cakefest 2017: CakePHP in a Containerized (CI/CD) environment

I suggest reading about docker-compose, traefik and portainer if you would like to use something like a web-gui

1 Like

Thanks! I’ll give it a look

So, I watched the video and the GitHub posted by BizDev. In order to clarify my understanding of the subject, Stefan shows how to:

  1. Create a Docker container for MySQL
  2. Create a Docker container for a fresh app, attached to the MySQL container and the database there created

He states that containers are stateless. Does that mean that the if the MySQL Docker container stops, the database is lost? I understand that it can be persisted, as it says in the MySQL Docker page linked by Stefan.

Anyway, if I have a Linux server, one strategy might be to containerize only CakePHP, and use connection strings pointing to the server’s MySQL? The Docker instance can see the hypervisor?

As you guys can see, I have more questions than answers with this subject.

Saludos,

Docker defines volumes, everything that is not in a mounted volume is lost on container deletion/upgrade.
For example, MySQL/MariaDB container you should mount the volume /var/lib/mysql to /var/clients/client1/db.

Yes, you can have multiples instances of the same image in the same host:
Example:

  • cake_app_1
    • volume /srv/client1/uploads:/app/webroot/img/upload
    • volume /srv/client1/logs:/app/webroot/logs
    • env DATABASE_URI=mysql://app1:secret@db/app1
    • map port 8081:80
  • cake_app_2
    • volume /srv/client2/uploads:/app/webroot/img/upload
    • volume /srv/client2/logs:/app/webroot/logs
    • env DATABASE_URI=mysql://app2:secret@db/app2
    • map port 8082:80
  • cake_app_testing
    • (explicitly i don’t define upload for testing, every upload will be lost on testing upgrade)
    • volume /srv/testing/logs:/app/webroot/logs
    • env DATABASE_URI=mysql://testing:testing@db/testing
    • map port 8083:80
  • db: mariadb:10.3
    • volume /srv/db:/var/lib/mysql
  • pma: phpmyadmin:latest
    • env PMA_HOST=db
    • map port 8084:80

I could define another db instance only for testing without volume, so that when redeploying testing, it would run migrations again from empty database.

Of course you would want every client to access the app via app.client-domain.com:80, for that you have to use a load balancer like traefik, nginx or caddy

Traefik use the same docker socket to discover every container, but you have to pass it as a volume.
If you refer to other hypervisrors (virtualbox, vmware, etc) then no, other solutions like kubernetes/docker-machine can create and use other hosts, although that is more advanced (you would have to centralize volumes, logs, or fix instances to hosts, etc)

Its a whole new topic. But gives you more control/scalability than classic vms/vps for each client.

Raul, thanks for your answer. It gives me a lot to think about and a lot to test!

Saludos,