Skip to content

Commit

Permalink
adding docs about deploying apps w/ dockerfile
Browse files Browse the repository at this point in the history
  • Loading branch information
nettoclaudio committed Jun 26, 2023
1 parent 7389547 commit 7478a64
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 3 deletions.
33 changes: 31 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
site_name: tsuru
site_name: Tsuru Docs
site_url: https://docs.github.com
site_author: Tsuru

Expand All @@ -13,7 +13,36 @@ theme:
palette:
primary: black

features:
- content.code.copy
- content.code.select
- navigation.instant
- navigation.tracking
- navigation.tabs
- toc.follow

markdown_extensions:
- admonition
- footnotes
- pymdownx.details
- pymdownx.highlight
- pymdownx.snippets:
base_path:
- src/
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- toc:
permalink: true

docs_dir: src

nav:
- Home: src/index.md
- Home: index.md
- Getting started: []
- User guides:
- Deploy:
- Using Dockerfile: ./user_guides/deploy_using_dockerfile.md
- Admin guides: []
- References: []
- Contributing: []
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ readme = "README.md"
python = "^3.11"
mkdocs = "^1.4.3"
mkdocs-material = "^9.1.17"
pymdown-extensions = "^10.0.1"

[build-system]
requires = ["poetry-core"]
Expand Down
24 changes: 24 additions & 0 deletions src/static/samples/dockerfile_v1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM golang:1.20-alpine3.17 AS builder
COPY ./ /go/app/
RUN set -x \
&& cd /go/app\
&& CGO_ENABLED=0 go build -o server ./main.go

# NOTE: Tsuru doesn't support deploy of distroless container images.
FROM alpine:3.17

# You should always set the working dir so Tsuru will try to find the config
# files (Procfile, tsuru.yaml) from there.
WORKDIR /var/app

# Copying generated file from previous build stage \o/
COPY --from=builder /go/app/server /var/app/

# Copying app's config file to working dir.
COPY ./tsuru.yaml /var/app

# NOTE: Container runtime doesn't expand the env var ($PORT), so we have to
# call a shell interpreter to do so.
#
# See more: https://github.com/moby/moby/issues/5509
CMD ["sh", "-c", "/var/app/server -port $PORT"]
3 changes: 3 additions & 0 deletions src/static/samples/dockerfile_v1/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/tsuru/samples/dockerfile_v1

go 1.20
39 changes: 39 additions & 0 deletions src/static/samples/dockerfile_v1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"flag"
"fmt"
"net/http"
)

func main() {
var port int

flag.IntVar(&port, "port", 8080, "TCP port number where app should wait for connections")
flag.Parse()

mux := http.NewServeMux()
mux.HandleFunc("/healthz", healthz)
mux.HandleFunc("/", hello)

address := fmt.Sprintf(":%d", port)

fmt.Println("Running web server on", address)

server := &http.Server{
Addr: address,
Handler: mux,
}

server.ListenAndServe()

fmt.Println("Web server turned off")
}

func healthz(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "WORKING")
}

func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello world!")
}
2 changes: 2 additions & 0 deletions src/static/samples/dockerfile_v1/tsuru.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
healthcheck:
path: /healthz
109 changes: 109 additions & 0 deletions src/user_guides/deploy_using_dockerfile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Deploy using Dockerfile

The Tsuru official platforms do not support every language, framework, or runtime that your tech stack may require, nor do they intend to.
If you have a setup where the official platforms do not meet your needs, you have the option to deploy your app using its [Dockerfile][Dockerfile reference] (Containerfile).

!!! note "Comparison: container image x Dockerfile"

The key difference between deploying an app using a container image and a Dockerfile lies in the developer's convenience.
The former requires additional steps on the developer's side, such as building and publishing the container image, while the latter eliminates these requirements.

## Usage

The command argument `--dockerfile` (in the `tsuru app deploy` command) is the main difference among other types of deploy on Tsuru.
It defines the container file that generates the container image used in the following steps of the app's deployment process.
Along this command, you also can pass all deployable files to the app - these files will be available in the container image build context, so you can select these using the [COPY](https://docs.docker.com/engine/reference/builder/#copy)/[ADD](https://docs.docker.com/engine/reference/builder/#add) directives.

The anatomy of app deploy using Dockerfile follows:

``` { .bash .no-copy }
tsuru app deploy -a <APP NAME> \
--dockerfile <PATH TO CONTAINER FILE> [--] [DEPLOYABLE FILES...]
```

The `--dockerfile` command argument value can be either a regular file or a directory.
When specifying a regular file, you have the explicit choice to select the container file.
On the other hand, when using a directory, the container file is implicitly chosen (see the heuristic mentioned below).

???+ notice "Heuristics for implicit container file name"

When you pass a directory as argument value of `--dockerfile`, the Tsuru client tries to find the container file following these names (order matters):

1. `Dockerfile.<APP NAME>` (e.g. `Dockerfile.my-example-app`)
2. `Containerfile.<APP NAME>` (e.g. `Containerfile.my-example-app`)
3. `Dockerfile.tsuru`
4. `Containerfile.tsuru`
5. `Dockerfile`
6. `Containerfile`

The chosen file will be the first one that exists and can be read correctly.

In both cases, you can push the deployable file(s) to `tsuru app deploy` passing as command arguments (positional args in the end of command).
Those files can either be regular files, directories or symbolic links.
Thoses files will be available in the container image build context and you shoul pick them usin `COPY`/`ADD` directives inside the container image.

???+ tip "Excluding deployable files with ignore files (`.tsuruignore` and `.dockerignore`)"

Please note that any deployable files can be excluded if they match a rule specified in the Tsuru ignore file (namely `.tsuruignore`) located in the current directory.
Furthermore, when deploying using a Dockerfile, the Tsuru client also takes into account the Docker ignore file (namely `.dockerfile`) in the current directory to exclude specific files.

### Example

In this example, we are about to build and deploy an app written in Golang.
You can copy and paste the used files below (separated by tabs) - before you might want take a closer look at them, specially at `Dockerfile` and `main.go` files.


=== "Dockerfile"

``` dockerfile
--8<-- "static/samples/dockerfile_v1/Dockerfile"
```

=== "main.go"

``` golang
--8<-- "static/samples/dockerfile_v1/main.go"
```

=== "go.mod"

``` gomod
--8<-- "static/samples/dockerfile_v1/go.mod"
```

=== "tsuru.yaml"

``` yaml
--8<-- "static/samples/dockerfile_v1/tsuru.yaml"
```

To deploy into application `my-example-app` using its Dockerfile, you just need issue the below command:

``` bash
tsuru app deploy -a my-example-app --dockerfile .
```

## Advanced

### How can I access Tsuru env vars during container image build?

You are able to import the env vars configured on Tsuru app while running the deploy with Dockerfile.
To do so, you just need append the following snippet in the Dockerfile.

``` dockerfile
RUN --mount=type=secret,id=tsuru-app-envvars,target=/var/run/secrets/envs.sh \
&& . /var/run/secrets/envs.sh \
... following commands in this multi-command line are able to see the env vars from Tsuru
```

**NOTE**: That's a bit different than defining `ENV` directive, specially because they're not stored in the image layers.

## Limitations

1. You cannot use distroless based images on your final container image - although on intermediary stages is fine.[^1]
2. There's no support for setting build arguments.
3. There's no support to specify a particular platform - the only platform supported is `linux/amd64`.

[^1]: Tsuru requires a shell intepreter (e.g. `sh` or `bash`) to run hooks, app shell, etc.

[Dockerfile reference]: https://docs.docker.com/engine/reference/builder/

0 comments on commit 7478a64

Please sign in to comment.