php-actions / php-build

Fast builds for repositories using php-actions.
9 stars 9 forks source link

Use alpine linux instead of ubuntu ? #1

Closed williamdes closed 3 years ago

williamdes commented 3 years ago

Hi, I just found out the project and the composer action, it looks good but seems to be very large to download. Maybe using alpine linux could improve things ?

williamdes commented 3 years ago

Anyway, using chained commands will reduce the number of "layers" that make the docker image. https://github.com/php-actions/php-build/blob/11a2d316b66b7d72018d0be3d1320da67d69faca/Dockerfile#L3

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ (copied most of the interesting chapter)

Each ENV line creates a new intermediate layer, just like RUN commands. This means that even if you unset the environment variable in a future layer, it still persists in this layer and its value can’t be dumped. You can test this by creating a Dockerfile like the following, and then building it.

FROM alpine
ENV ADMIN_USER="mark"
RUN echo $ADMIN_USER > ./mark
RUN unset ADMIN_USER

To prevent this, and really unset the environment variable, use a RUN command with shell commands, to set, use, and unset the variable all in a single layer. You can separate your commands with ; or &&. If you use the second method, and one of the commands fails, the docker build also fails. This is usually a good idea. Using \ as a line continuation character for Linux Dockerfiles improves readability. You could also put all of the commands into a shell script and have the RUN command just run that shell script.

FROM alpine
RUN export ADMIN_USER="mark" \
&& echo $ADMIN_USER > ./mark \
&& unset ADMIN_USER
CMD sh
g105b commented 3 years ago

Hi @williamdes ,

Thanks for reporting this. I have recently been building this Docker image so that the php-actions repositories can enjoy the benefit of having multiple versions of PHP, Composer, PHPUnit, etc. available, for switching within the action's yml config.

I am by no means a Docker expert, and I was quite disappointed in seeing how long it takes to run the actions after I implemented this (about 2 mins).

I will take a look into using Alpine instead of Ubuntu. I chose Ubuntu because of the familiar package management, as well as being the OS used by Github Actions themselves -- I thought that it would be able to cache the layers and not have to rebuild anything.

Anyway, thanks again for raising this. I'll make some amends and update this issue with what I find. Please feel free in helping out in any way, as Docker is a complex world for me.

Thanks, Greg.

williamdes commented 3 years ago

Hi,

I will maybe give some help depending on my free hours, better is to post here so I can reply ;) Docker is a tool I use a lot and I can help with tricky details. Here is an example for my image: https://github.com/wdesportes/docker-web/blob/master/Dockerfile

baschny commented 3 years ago

Great small community here, I could also offer some help! Thanks for the kick off!

I have been building docker container for our PHP purposes for some years now, and started using GitHub Actions in our projects lately and stumbled over these "official looking" actions. I could also be willing to help here.

My first impression was also that the image size could be improved, and Alpine would be a good starting point. Combined with that, why not use the official PHP docker images as a base in order to increase cacheability of the layers? We have been doing that in our projects and its pretty stable, the Alpine flavors of the official images are very good and easy to improve upon (and we don't need to keep track of newer versions, etc).

A separate docker image per PHP version would also be more appropriate, because nobody needs multiple variants in one go.

Just some random first thoughts.

g105b commented 3 years ago

Hi @baschny ,

I would much prefer not to have to package up my own Docker image, but I can't think of any way to provide the ability for a developer to choose their PHP version from their action's YAML config.

The developer needs to be able to specify the PHP version that is being used within the action, as well as the version of the action's binary itself. For example, a developer may have their project require PHPUnit v8 and run within PHP 7.3. I want these actions to be capable of doing that.

The only way I can think of achieving this is to bundle each supported PHP binary in the base Docker image, symlinking the correct version that's specified at runtime from the action's yaml.

There might be a much better way of achieving this, so I'm open to improvements. I'm currently building the Alpine image to test with, I'll update this thread when I can show you.

baschny commented 3 years ago

AFAIK you can use variables in the image part of your action.yml:

runs:
  using: 'docker'
  image: 'Dockerfile'

So using different images based on input variables would be possible in a single action. And if I understand it correctly, if you provide pre-build images (i.e. in docker hub) instead of using Dockerfile it would speed up the running of the actions considerably. I might test this and bring back my experience with it some day.

g105b commented 3 years ago

That sounds fantastic. I will read about the image part of the yaml - it might be the solution we need.

baschny commented 3 years ago

Something like that (untested) to use one of the official images:

runs: 
  using: 'docker'
  image: 'docker://php:${{ inputs.php_version }}-alpine'
baschny commented 3 years ago

you can even use GitHub actions to build the images and upload them to the registry of docker hub (maybe you could create a "php-actions" Orga there to keep them separate from your private docker hub space). Just ideas :)

baschny commented 3 years ago

Unfortunately using "inputs" in the "image:" line doesn't seem to be supported, at least in my tests got the error:

Error: /home/runner/work/xxxx/./.github/actions/composer/action.yml (Line: 25, Col: 10): Unrecognized named-value: 'inputs'. Located at position 1 within expression: inputs.composer_version
3

When I tried simply using the official composer image:

runs:
  using: 'docker'
  image: "docker://composer:${{ inputs.composer_version }}"
  args:
    - ${{ inputs.command }}
    - ${{ inputs.args }}

There is unfortunately very little documentation (and examples) on the possibilities in the action.yml. Will postpone the research for another time, if you find out how it can be done, just comment here.

baschny commented 3 years ago

I continued trying it out and managed to create a POC around the idea of calling dynamically different docker containers depending on the "input". But the result turned out to be not using the using: docker (as there is no way of passing build-args to docker currently to it) but using: composite and having a shell script doing the heavy lifting around it. This way also solves the caching problem, since we can "manipulate" the cache directory that the composer container uses.

And this doesn't even require a Dockerfile or any other script, its simply action.yml using the official composer package. Once the package is pulled, it calls it in less than 2 seconds.

Since it uses a completely different approach, I didn't manage to contribute it as a Pull request, but feel free to take a look at it and share your ideas on it: https://github.com/baschny/php-composer-action - I will probably start using that in our projects and see how it goes.

g105b commented 3 years ago

Hey @baschny,

This looks fantastic - thanks so much for your contributions here. I'm certainly going to implement this. My idea of using the custom base image just isn't the right direction, but I didn't know you could run docker commands within the action itself. I'll test this out today and if it works well it can be the basis of all the php-actions repos.

Greg.

williamdes commented 3 years ago

Hi @g105b You can make pull-requests to your yourself ? and feel free to ask me to review them, maybe @baschny would like to review them too ?

g105b commented 3 years ago

Yeah I'll submit the concept as a PR so we can make sure we get the best design possible.

g105b commented 3 years ago

Hi @williamdes and @baschny,

I've made a PR on the php-actions/composer repository and described what's changed in there. Please see: https://github.com/php-actions/composer/pull/27

I think I will close down this repository after phpunit, phpstan and composer repositories all use this new style.

Thanks, Greg.

g105b commented 3 years ago

Implemented