Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker Install #326

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Docker

on:
workflow_dispatch:
inputs:
tagInput:
description: 'Tag'
required: true

release:
types: [created]
tags:
- 'v*'

jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to Docker Hub
uses: docker/login-action@v2
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Determine version tag
id: version-tag
run: |
INPUT_VALUE="${{ github.event.inputs.tagInput }}"
if [ -z "$INPUT_VALUE" ]; then
INPUT_VALUE="${{ github.ref_name }}"
fi
echo "::set-output name=value::$INPUT_VALUE"
-
name: Build and push
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
tighten/takeout:latest
tighten/takeout:${{ steps.version-tag.outputs.value }}
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM php:8.1-cli-alpine

ENV TAKEOUT_CONTAINER=1

COPY --from=docker/buildx-bin /buildx /usr/libexec/docker/cli-plugins/docker-buildx

# Install the PHP extensions & Docker
RUN apk add --no-cache --update docker openrc ncurses \
&& docker-php-ext-configure pcntl --enable-pcntl \
&& docker-php-ext-install -j$(nproc) pcntl \
&& rc-update add docker boot

WORKDIR /takeout

COPY builds/takeout /usr/local/bin/takeout

ENTRYPOINT ["takeout"]

37 changes: 31 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@ But you can also easily enable ElasticSearch, PostgreSQL, MSSQL, Mongo, Redis, a
## Requirements

- macOS, Linux, Windows 10 or WSL2
- [Composer](https://getcomposer.org/) installed
- Docker installed (macOS: [Docker for Mac](https://docs.docker.com/docker-for-mac/), Windows: [Docker for Windows](https://docs.docker.com/docker-for-windows/))

## Installation

Install Takeout with Composer by running:
To install Takeout locally, add this alias to your `~/.bashrc` (or similar):

```bash
composer global require "tightenco/takeout:~2.7"
alias takeout="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -it tighten/takeout:latest"
```

Make sure the `~/.composer/vendor/bin` directory is in your system's "PATH".
_Note: Previous versions of Takeout required installing it via `composer global require`. That's discouraged now and the Docker image is the preferred way._

## Usage

Expand Down Expand Up @@ -243,7 +242,6 @@ The best way to see our future plans is to check out the [Projects Board](https:

If you're working with us and are assigned to push a release, here's the easiest process:


1. Visit the [Takeout Releases page](https://github.com/tighten/takeout/releases); figure out what your next tag will be (increase the third number if it's a patch or fix; increase the second number if it's adding features)
2. On your local machine, pull down the latest version of `main` (`git checkout main && git pull`)
3. Build for the version you're targeting (`php ./takeout app:build`)
Expand All @@ -252,4 +250,31 @@ If you're working with us and are assigned to push a release, here's the easiest
6. [Draft a new release](https://github.com/tighten/takeout/releases/new) with both the tag version and release title of your tag (e.g. `v1.5.1`)
7. Use the "Generate release notes" button to generate release notes from the merged PRs.
8. Hit `Publish release`
9. Profit 😆
9. The new tag and release will trigger the [`docker-publish.yml`](.github/workflows/docker-publish.yml) workflow, which should take care of building and pushing the new image of the Docker container (see the "Building The Docker Image Manually" section below)
10. Profit 😆

## Building The Docker Image Manually

The important thing is to remember to build both `linux/amd64` and `linux/arm64` images. We rely on Docker's `buildx` command, which uses Docker's [BuildKit](https://github.com/moby/buildkit) behind the scenes, which allows us to build for multiple platforms, independently of the platform of the machine building the image.

You may build and publish a new version of the docker image using the following command:

```bash
docker buildx build --platform=linux/amd64,linux/arm64 -t tighten/takeout:latest --push .
```

If it's the first time you're building the image, you may get the following error:

```
ERROR: Multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
```

This means that you first need to create a builder container, which you maydo like so:

```bash
docker buildx create --use
```

After that, retrying the `buildx` command should work.

Please, note that building the container will simply copy the current version of the Takeout `phar` file at [builds/takeout](./builds/takeout) to inside the container and publish that, so make sure you have to most recent version built locally. If you don't, follow the release process to build the new version before building the Docker image.
19 changes: 5 additions & 14 deletions app/Shell/DockerTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,18 @@ public function getLatestTag(): string
public function getTags(): Collection
{
$response = json_decode($this->getTagsResponse()->getContents(), true);

$platform = $this->platform();

return collect($response['results'])
->when(in_array($platform, $this->armArchitectures, true), $this->armSupportedImagesOnlyFilter())
->when(! in_array($platform, $this->armArchitectures, true), $this->nonArmOnlySupportImagesFilter())
->when(in_array($platform, $this->armArchitectures, true), $this->onlyArmImagesFilter())
->when(! in_array($platform, $this->armArchitectures, true), $this->onlyNonArmImagesFilter())
->pluck('name')
->sort(new VersionComparator)
->values();
}

/**
* Return a function intended to filter tags, ensuring images that do not support arm architecture are filtered out.
*
* @return callable
*/
protected function armSupportedImagesOnlyFilter()
protected function onlyArmImagesFilter()
{
return function ($tags) {
return $tags->filter(function ($tag) {
Expand All @@ -76,12 +72,7 @@ protected function armSupportedImagesOnlyFilter()
};
}

/**
* Return a function intended to filter tags, that ensures are arm-only images are filtered out.
*
* @return callable
*/
protected function nonArmOnlySupportImagesFilter()
protected function onlyNonArmImagesFilter()
{
return function ($tags) {
return $tags->filter(function ($tag) {
Expand Down
29 changes: 20 additions & 9 deletions tests/Feature/DockerTagsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Mockery as M;
use Tests\Support\IntelDockerTags;
use Tests\Support\M1DockerTags;
use Tests\Support\FakePlatformDockerTags;
use Tests\TestCase;

class DockerTagsTest extends TestCase
{
public static function armPlatforms(): array
{
return [
[FakePlatformDockerTags::M1_ARM_PLATFORM],
[FakePlatformDockerTags::LINUX_ARM_PLATFORM],
];
}

/** @test */
function it_gets_the_latest_tag_not_named_latest()
{
Expand Down Expand Up @@ -45,14 +52,17 @@ function it_sorts_the_versions_naturally()
$this->assertEquals('16.2', $tags->shift());
}

/** @test */
function it_detects_arm64_based_images_when_running_on_arm64_based_host()
/**
* @test
*
* @dataProvider armPlatforms
*/
function it_detects_arm_based_images_when_running_on_arm64_based_host($platform)
{
$handlerStack = HandlerStack::create($this->mockImagesResponseHandler());
$client = new Client(['handler' => $handlerStack]);

/** @var DockerTags $dockerTags */
$dockerTags = M::mock(M1DockerTags::class, [$client, app(MySql::class)])->makePartial();
$dockerTags = (new FakePlatformDockerTags($client, app(MySql::class)))->withFakePlatform($platform);

$this->assertEquals('1.0.0-arm64', $dockerTags->getLatestTag());
}
Expand All @@ -63,8 +73,7 @@ function it_gets_latest_tag_on_intel_platform()
$handlerStack = HandlerStack::create($this->mockImagesResponseHandler());
$client = new Client(['handler' => $handlerStack]);

/** @var DockerTags $dockerTags */
$dockerTags = M::mock(IntelDockerTags::class, [$client, app(MySql::class)])->makePartial();
$dockerTags = (new FakePlatformDockerTags($client, app(MySql::class)))->withFakePlatform(FakePlatformDockerTags::INTEL_ARM_PLATFORM);

$this->assertEquals('1.0.0', $dockerTags->getLatestTag());
}
Expand All @@ -77,20 +86,22 @@ private function mockImagesResponseHandler()
[
'name' => 'latest',
'images' => [
['architecture' => 'x86_64'],
['architecture' => 'amd64'],
['architecture' => 'arm64'],
],
],
[
'name' => '1.0.0',
'images' => [
['architecture' => 'x86_64'],
['architecture' => 'amd64'],
],
],
[
'name' => '1.0.0-arm64',
'images' => [
['architecture' => 'arm64'],
['architecture' => 'aarch64'],
],
],
],
Expand Down
26 changes: 26 additions & 0 deletions tests/Support/FakePlatformDockerTags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Tests\Support;

use App\Shell\DockerTags;

class FakePlatformDockerTags extends DockerTags
{
const M1_ARM_PLATFORM = 'arm64';
const LINUX_ARM_PLATFORM = 'aarch64';
const INTEL_ARM_PLATFORM = 'x86_64';

protected string $fakePlatform;

public function withFakePlatform(string $platform): self
{
$this->fakePlatform = $platform;

return $this;
}

protected function platform(): string
{
return $this->fakePlatform;
}
}
13 changes: 0 additions & 13 deletions tests/Support/IntelDockerTags.php

This file was deleted.

13 changes: 0 additions & 13 deletions tests/Support/M1DockerTags.php

This file was deleted.

Loading