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

Merged
merged 27 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3e938b5
Adds the Dockerfile we can use to build the new image
tonysm Oct 26, 2023
0bbe2b8
Adds a workflow that will build and publish the Docker image whenever…
tonysm Oct 27, 2023
63ad63c
Update install instructions
tonysm Oct 27, 2023
fd3db36
Tweaks wording
tonysm Oct 27, 2023
136c7ce
Fix default postgres version has been updated
tonysm Oct 27, 2023
c3df03d
Remove unused dependencies
tonysm Oct 27, 2023
2eae549
Drop the mention of composer global require
tonysm Oct 27, 2023
4de5754
Adds ncurses package for the cli-menu
tonysm Oct 27, 2023
cdeecdf
Fix alpine ARM64 uname is different than macos
tonysm Oct 27, 2023
c33a95c
Tweaks the platform check code
tonysm Oct 28, 2023
a3978b5
Simplify the platform tests
tonysm Nov 3, 2023
a2997fd
Tweaks the README
tonysm Nov 3, 2023
f5a786e
Fix tlint
tonysm Nov 3, 2023
290de4f
Adds docs for manually building and publishing the docker image
tonysm Nov 3, 2023
4eb995e
wip
tonysm Nov 3, 2023
f3f0ebd
wip
tonysm Nov 3, 2023
58a23c1
Adds a TAKEOUT_CONTAINER env variable inside the container (which we …
tonysm Nov 3, 2023
9aa200e
Tweaks
tonysm Nov 4, 2023
a8a6e9a
Merge branch 'main' into tm/docker-install
tonysm May 5, 2024
59f3df9
Merge branch 'main' into tm/docker-install
tonysm Jun 14, 2024
049672e
Merge branch 'main' into tm/docker-install
tonysm Dec 6, 2024
0f83b0e
wording
tonysm Dec 6, 2024
13be11c
Adds the Windows alias tweak
tonysm Dec 7, 2024
1fd7157
Wording
tonysm Dec 7, 2024
060a03a
Adds the powershell version of the alias
tonysm Dec 7, 2024
6563066
Bump the actions versions
tonysm Dec 9, 2024
4468c35
Tweaks
tonysm Dec 16, 2024
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
tonysm marked this conversation as resolved.
Show resolved Hide resolved
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
tonysm marked this conversation as resolved.
Show resolved Hide resolved
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
tonysm marked this conversation as resolved.
Show resolved Hide resolved
-
name: Login to Docker Hub
uses: docker/login-action@v2
tonysm marked this conversation as resolved.
Show resolved Hide resolved
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
tonysm marked this conversation as resolved.
Show resolved Hide resolved
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking forward to being able to bump this 🙌


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"]

57 changes: 53 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,40 @@ 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/))

If you opt for the PHP/Composer installation, you also need:

- PHP installed (latest major version)
- Composer installed

## Installation

Install Takeout with Composer by running:
The recommended way to install Takeout is the dockerized version via an alias (add this to your `~/.bashrc`, `~/.zshrc` or equivalent).

On Linux or macOS, use:

```bash
alias takeout="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -it tighten/takeout:latest"
```

On Windows, use:

```bash
alias takeout="docker run --rm -v //var/run/docker.sock:/var/run/docker.sock -it tighten/takeout:latest"
```

That's it. You may now use Takeout on your terminal. The first time you use this alias, it will pull the Takeout image from Docker Hub.

To update the image, run `docker pull tighten/takeout` when you want to get the newest release.

Otherwise, if you have a PHP environment available, you may install Takeout via Composer:

```bash
composer global require "tightenco/takeout:~2.8"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we be bumping to 3.0 with this release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uhm, maybe we can tag a 2.9 now, and then switch to 3.0 once we upgrade it to the major PHP version?

tonysm marked this conversation as resolved.
Show resolved Hide resolved
```

Make sure the `~/.composer/vendor/bin` directory is in your system's "PATH".
If you use the PHP/Composer installation, make sure you're on the latest version of PHP. We'll only support the current major version of PHP using this installation approach.

## Usage

Expand Down Expand Up @@ -274,4 +296,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('17.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