Skip to content

Commit

Permalink
docs(examples): add build dependencies example
Browse files Browse the repository at this point in the history
  • Loading branch information
eysi09 committed Mar 18, 2020
1 parent cf04087 commit 600e6ac
Show file tree
Hide file tree
Showing 17 changed files with 1,306 additions and 0 deletions.
75 changes: 75 additions & 0 deletions examples/build-dependencies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Build Dependencies

This example project demonstrates how to use build dependencies to include files and directories from outside a module's root with its build context. For example, some .NET and Java projects that are split up into multiple modules need a shared configuration file at build time for each module.

Another common use case is to use build dependencies to include shared libraries with multiple modules. Our [`openfaas` example project](../openfaas) demonstrates this same pattern with an NPM package.

To achieve this, we:

1. wrap the shared files/directories in an `exec` module
2. reference it in the [build dependency](https://docs.garden.io/reference/module-types/container#build-dependencies) field of the consuming modules.

## Project Structure

The project consists of a `shared-config` module of type `exec`, and two container modules, `frontend` and `backend`, that have a build dependency on the `shared-config` module.

The `shared-config` module contains a single `config.env` file and the following Garden config:

```yaml
# shared-config/garden.yml
kind: Module
name: shared-config
type: exec
```
The `build` config for both the `frontend` and `backend` looks like this:

```yaml
# frontend/garden.yml (same for backend/garden.yml)
build:
dependencies:
- name: shared-config
copy:
- source: "config.env"
target: "config/"
```

This tells Garden to first "build" the `shared-config` module, then to copy the contents from the `source` path *in the `shared-config` module* to the `target` path *in the `frontend` module*.

Note that this takes place inside the `.garden/build` directory. For example, if you run `garden build frontend` and then look at the folder structure of the `.garden/build` directory, you'll see:

```console
$ tree .garden/build/frontend -L 2
.garden/build/frontend
├── config
│   └── config.env # <--- The shared config file
├── Dockerfile
├── app.js
├── ...
```

This is the build context Garden will use when building the `frontend` module.

In this example there's no "build" step for the `exec` module, but you can add it via the `build` field. Check out our [`local-exec` project](../local-exec/backend/garden.yml) for an example of this.

## Usage

Run `garden deploy` to deploy the project. You can verify that it works by running:

```sh
garden call frontend
```

It'll print the contents of the `shared-config/config.env` file:

```sh
Call 📞
✔ providers → Getting status... → Done
✔ Sending HTTP GET request to http://eysi-build-dependencies.dev-1.sys.garden/hello-frontend
200 OK
Config says: Hello World
```
4 changes: 4 additions & 0 deletions examples/build-dependencies/backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
Dockerfile
garden.yml
app.yaml
27 changes: 27 additions & 0 deletions examples/build-dependencies/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof

.vscode/settings.json
webserver/*server*
11 changes: 11 additions & 0 deletions examples/build-dependencies/backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM golang:1.8.3-alpine

ENV PORT=8080
EXPOSE ${PORT}
WORKDIR /app

COPY main.go .

RUN go build -o main .

ENTRYPOINT ["./main"]
23 changes: 23 additions & 0 deletions examples/build-dependencies/backend/garden.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
kind: Module
name: backend
description: Backend service container
type: container
build:
dependencies:
- name: shared-config
copy:
- source: "config.env"
target: "config/"
services:
- name: backend
ports:
- name: http
containerPort: 8080
# Maps service:80 -> container:8080
servicePort: 80
ingresses:
- path: /hello-backend
port: http
tasks:
- name: test
command: ["sh", "-c", "echo task output"]
17 changes: 17 additions & 0 deletions examples/build-dependencies/backend/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"fmt"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello from Go!")
}

func main() {
http.HandleFunc("/hello-backend", handler)
fmt.Println("Server running...")

http.ListenAndServe(":8080", nil)
}
4 changes: 4 additions & 0 deletions examples/build-dependencies/frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
Dockerfile
garden.yml
app.yaml
12 changes: 12 additions & 0 deletions examples/build-dependencies/frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM node:9-alpine

ENV PORT=8080
EXPOSE ${PORT}
WORKDIR /app

COPY package.json /app
RUN npm install

COPY . /app

CMD ["npm", "start"]
30 changes: 30 additions & 0 deletions examples/build-dependencies/frontend/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const express = require('express');
const request = require('request-promise')
const path = require('path')
const dotenv = require('dotenv')
const app = express();

const config = dotenv.config({ path: path.resolve(process.cwd(), "config", "config.env") })
const backendServiceEndpoint = `http://backend/hello-backend`

app.get('/hello-frontend', (req, res) => res.send(`Config says: ${config.parsed.MESSAGE}`));

app.get('/call-backend', (req, res) => {
// Query the backend and return the response
request.get(backendServiceEndpoint)
.then(message => {
message = `Backend says: '${message}'`
res.json({
message,
})
})
.catch(err => {
res.statusCode = 500
res.json({
error: err,
message: "Unable to reach service at " + backendServiceEndpoint,
})
});
});

module.exports = { app }
33 changes: 33 additions & 0 deletions examples/build-dependencies/frontend/garden.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
kind: Module
name: frontend
description: Frontend service container
type: container
build:
dependencies:
- name: shared-config
copy:
- source: "config.env"
target: "config/"
services:
- name: frontend
ports:
- name: http
containerPort: 8080
healthCheck:
httpGet:
path: /hello-frontend
port: http
ingresses:
- path: /hello-frontend
port: http
- path: /call-backend
port: http
dependencies:
- backend
tests:
- name: unit
args: [npm, test]
- name: integ
args: [npm, run, integ]
dependencies:
- frontend
3 changes: 3 additions & 0 deletions examples/build-dependencies/frontend/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { app } = require('./app');

app.listen(process.env.PORT, '0.0.0.0', () => console.log('Frontend service started'));
Loading

0 comments on commit 600e6ac

Please sign in to comment.