brefphp / bref

Serverless PHP on AWS Lambda
https://bref.sh
MIT License
3.15k stars 365 forks source link

Docker images #237

Closed deleugpn closed 5 years ago

deleugpn commented 5 years ago

Would it be easy or possible for Bref to provide one Docker image that contains the exact same php binary that the lambda layer has which we could use on our CI / CD build process to install composer and run phpunit? I know I can easily build a container myself to do this, but I would like to make sure that my tests run as close as the production php binary will be (e.g. am I using an extension that the lambda doesn't have, but my unit tests will flag?). I'm not sure how easy it would be for bref to maintain an image like that on Docker Hub.

mnapoli commented 5 years ago

Honestly I'm not sure how much work would that be. It could be a possibility, just to let you know at the moment however I am focusing on other issues and the documentation.

deleugpn commented 5 years ago

I'm looking this again and I think I found out how simple it is. I made an organization on Docker Hub called breftest (the name bref is still available) and created a repository called php (https://hub.docker.com/r/breftest/php). The goal is to have the Docker image with the PHP binary for lambda available (https://github.com/mnapoli/bref/blob/master/runtime/php/php.Dockerfile#L485-L496). If this particular image gets built and pushed to Docker Hub (preferably under the official library), then we can use it to run things like composer install, php artisan route:cache or any other project-specific setting as well as ./vendor/bin/phpunit. If all the tests passes using that php binary, we know for a fact that we won't have any problems related to different php version or different extensions between local, test and production.

mnapoli commented 5 years ago

Very good points! I am more interested now in this issue as well. I went ahead and secured the "bref" team.

I am not that familiar with Docker Hub: when creating a repository should I create it from scratch, or create it linked to this GitHub repository? (we may need to provide several Docker images over time)

deleugpn commented 5 years ago

I don't have experience with Docker Hub either as I'm mostly using AWS ECR. However I feel like the Docker Hub integration with GitHub is just a facilitator tool that will listen to push events and build the images for you automatically. My suggestion would be to just add a docker push in your existing build script and only worry about automating it some other time if it makes sense to dig deeper into that.

I just got a huge milestone for a PHP pipeline: I built the images and pushed it to my repo (https://hub.docker.com/r/breftest/php/tags) and then I succeeded by running it like this:

      - docker run --name laravel-app -v $(pwd):/app -w /app -t breftest/php:73 sh -c "php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\" && php composer-setup.php && php composer.phar install && /app/vendor/bin/phpunit"
      - docker cp laravel-app:/app/vendor ./vendor

#      - aws cloudformation package --template-file ./serverless.yaml --s3-bucket ${S3_BUCKET} --output-template-file lambda.yaml

The first line will run the image that bref would provide, install composer, run composer install and run the tests. If successful, we would copy the vendor folder from the container out to the host machine (in this case AWS CodeBuild) and then we have the source code ready to be packaged and deployed.

The reason for copying the vendor out is because an AWS CodePipeline is listening to GitHub push events on a specific branch and running the pipeline. So when AWS CodeBuild starts, it has the source code, but GitHub doesn't have the vendor, so we use a container to make the vendor and run the tests. Then we can use the vendor from the container to combine it with the source code downloaded and already available in the host for the deploy.

mnapoli commented 5 years ago

Nice! I'll try to have a look into that soon.

deleugpn commented 5 years ago

In terms of getting the images ready, all you need to do is:

docker build -f ${PWD}/php.Dockerfile -t breftest/php:73 --build-arg zlib=1.2.11 --build-arg openssl=1.1.1a --build-arg libxml2=2.9.8 --build-arg libsodium=1.0.16 --build-arg libssh2=1.8.0 --build-arg curl=7.63.0 --build-arg postgres=9.6.11 --build-arg libzip=1.5.1 --build-arg php=7.3.2 .

This will make the image available on Docker Hub, which makes it available for us to use in any docker installation. If you need some inspiration for a Pipeline, I'm setting up a public test project here: https://github.com/deleugpn/laravel-lambda

mnapoli commented 5 years ago

@deleugpn thank you for the instructions!

To get things started I just pushed a latest version: https://cloud.docker.com/u/bref/repository/list

For example:

docker run --rm bref/php-73 php -v
zaherg commented 5 years ago

hey @mnapoli you can automate the whole thing, once you create a repository at docker hub, you can link it to GitHub this, in turn, will trigger an auto-build process for you, instead of building it locally and push it.

I am more than happy to help if there is anything I can do here to make the process smoother.

Also, you should use this link https://hub.docker.com/u/bref as the link you provided is the private one, not the public one.

mnapoli commented 5 years ago

@linuxjuggler thanks, we are working on this with @Guillaume-Rossignol.

The main problem we are facing is that we are publishing multiple images (php-72, php-73, php-72-fpm, etc.) with one repository. And that those images build from each other (so we can't just simply register the repository multiple times, there are dependencies between the images).

zaherg commented 5 years ago

@mnapoli true, but this is what I do when I have multiple versions in the same repository, all you have to do is to define various build rules for each file

Screen Shot 2019-08-06 at 2 59 11 PM

Each folder should contain a build hooks file which defines how you want the image to be built (example https://github.com/linuxjuggler/php-and-nginx).

This way you will have one image but multiple tags for example instead of

bref/php-72:latest

you will have something like:

push bref/php:72-latest // for the latest
push bref/php:72-dev // for the dev version

instead of having a repository for each PHP version/type.

I am not saying what you are doing is wrong, I am just providing a small suggestion to make things a bit easier in your end, but you know better than me if it will work or not.

mnapoli commented 5 years ago

@linuxjuggler thanks! This is indeed something we considered, but I find it very weird to "highjack" the version number to store different images.

I mean, php-73 and php-73-fpm are not the same images. I would find it very weird to store them in the same image and use a version number to separate them.

zaherg commented 5 years ago

Got your point, if there is anything I can be helpful with just let me know.

mnapoli commented 5 years ago

Thank you!

mnapoli commented 5 years ago

Here we go!

https://github.com/brefphp/bref/releases/tag/0.5.2