Merge pull request #2299 from spotify/rugvip/db

cli: forward docker args to backend:build-image, add --build flag, and use by default
This commit is contained in:
Patrik Oldsberg
2020-09-07 13:48:37 +02:00
committed by GitHub
14 changed files with 103 additions and 40 deletions
+6 -1
View File
@@ -1,9 +1,14 @@
FROM nginx:mainline
# The purpose of this image is to serve the frontend app content separately.
# By default the Backstage backend uses the app-backend plugin to serve the
# app from the backend itself, but it may be desirable to move the frontend
# content serving to a separate deployment, in which case this image can be used.
# This dockerfile requires the app to be built on the host first, as it
# simply copies in the build output into the image.
# The safest way to build this image is to use `yarn docker-build`
# The safest way to build this image is to use `yarn docker-build:app`
RUN apt-get update && apt-get -y install jq && rm -rf /var/lib/apt/lists/*
+11
View File
@@ -0,0 +1,11 @@
app:
baseUrl: http://localhost:3000
backend:
baseUrl: http://localhost:7000
listen:
port: 7000
cors:
origin: http://localhost:3000
methods: [GET, POST, PUT, DELETE]
credentials: true
+1 -5
View File
@@ -1,15 +1,11 @@
app:
title: Backstage Example App
baseUrl: http://localhost:3000
baseUrl: http://localhost:7000
backend:
baseUrl: http://localhost:7000
listen:
port: 7000
cors:
origin: http://localhost:3000
methods: [GET, POST, PUT, DELETE]
credentials: true
database:
client: sqlite3
connection: ':memory:'
+2 -6
View File
@@ -1,14 +1,10 @@
# Make sure that before you
# run the docker-compose that you have run
# $ yarn docker-build:all
# $ yarn docker-build
version: '3'
services:
frontend:
image: 'spotify/backstage:latest'
ports:
- '3000:80'
backend:
backstage:
image: 'example-backend:latest'
ports:
- '7000:7000'
+6 -7
View File
@@ -10,21 +10,20 @@ title: Other
Run the following commands if you have Docker environment
```bash
$ yarn install
$ yarn docker-build
$ docker run --rm -it -p 80:80 spotify/backstage
$ docker run --rm -it -p 7000:7000 -e NODE_ENV=development example-backend:latest
```
Then open http://localhost/ on your browser.
### Running with `docker-compose`
Run the following commands if you have docker and docker-compose for a full
example, with the example backend also deployed.
There is also a `docker-compose.yaml` that you can use to replace the previous
`docker run` command:
```bash
$ yarn docker-build:all
$ yarn install
$ yarn docker-build
$ docker-compose up
```
Then open http://localhost:3000 on your browser to see the example app with an
example backend.
+5 -7
View File
@@ -171,21 +171,19 @@ The frontend container can be built with a provided command.
```bash
yarn install
yarn tsc
yarn build
yarn run docker-build
yarn run docker-build:app
```
Running this will simply generate a Docker container containing the contents of
the UIs `dist` directory. The resulting container will be about 50MB in size.
the UIs `dist` directory.
The backend container can be built by running the following command in the
`packages/backend` directory.
The backend container can be built by running the following command:
```bash
yarn run build-image
yarn run docker-build
```
This will create a ~500MB container called `example-backend`.
This will create a container called `example-backend`.
The lighthouse-audit-service container is already publicly available in Docker
Hub and can be downloaded and ran with
+2 -2
View File
@@ -18,8 +18,8 @@
"lint:all": "lerna run lint --",
"lint:type-deps": "node scripts/check-type-dependencies.js",
"docgen": "lerna run docgen",
"docker-build": "yarn workspace example-app build && docker build . -t spotify/backstage",
"docker-build:all": "yarn tsc && yarn build && yarn docker-build && yarn workspace example-backend build-image",
"docker-build:app": "yarn workspace example-app build && docker build . -t spotify/backstage",
"docker-build": "yarn tsc && yarn workspace example-backend build-image",
"create-plugin": "backstage-cli create-plugin",
"remove-plugin": "backstage-cli remove-plugin",
"release": "if [ \"$(git symbolic-ref --short HEAD)\" = master ]; then echo \"don't try to release master\"; exit 1; else lerna version --no-push --force-publish; fi",
+1 -1
View File
@@ -10,7 +10,7 @@
},
"scripts": {
"build": "backstage-cli backend:build",
"build-image": "backstage-cli backend:build-image example-backend",
"build-image": "backstage-cli backend:build-image --build --tag example-backend",
"start": "backstage-cli backend:dev",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
@@ -15,28 +15,64 @@
*/
import fs from 'fs-extra';
import { join as joinPath, relative as relativePath } from 'path';
import { createDistWorkspace } from '../../lib/packager';
import { paths } from '../../lib/paths';
import { run } from '../../lib/run';
import { Command } from 'commander';
const PKG_PATH = 'package.json';
export default async (imageTag: string) => {
export default async (cmd: Command) => {
// Skip the preparation steps if we're being asked for help
if (cmd.args.includes('--help')) {
await run('docker', ['image', 'build', '--help']);
return;
}
const pkgPath = paths.resolveTarget(PKG_PATH);
const pkg = await fs.readJson(pkgPath);
const appConfigs = await findAppConfigs();
const tempDistWorkspace = await createDistWorkspace([pkg.name], {
buildDependencies: Boolean(cmd.build),
files: [
'package.json',
'yarn.lock',
'app-config.yaml',
...appConfigs,
{ src: paths.resolveTarget('Dockerfile'), dest: 'Dockerfile' },
],
});
console.log(`Dist workspace ready at ${tempDistWorkspace}`);
await run('docker', ['build', '.', '-t', imageTag], {
// all args are forwarded to docker build
await run('docker', ['image', 'build', '.', ...cmd.args], {
cwd: tempDistWorkspace,
});
await fs.remove(tempDistWorkspace);
};
/**
* Find all config files to copy into the image
*/
async function findAppConfigs(): Promise<string[]> {
const files = [];
for (const name of await fs.readdir(paths.targetRoot)) {
if (name.startsWith('app-config.') && name.endsWith('.yaml')) {
files.push(name);
}
}
if (paths.targetRoot !== paths.targetDir) {
const dirPath = relativePath(paths.targetRoot, paths.targetDir);
for (const name of await fs.readdir(paths.targetDir)) {
if (name.startsWith('app-config.') && name.endsWith('.yaml')) {
files.push(joinPath(dirPath, name));
}
}
}
return files;
}
+5 -2
View File
@@ -36,9 +36,12 @@ export function registerCommands(program: CommanderStatic) {
.action(lazy(() => import('./backend/build').then(m => m.default)));
program
.command('backend:build-image <image-tag>')
.command('backend:build-image')
.allowUnknownOption(true)
.helpOption(', --backstage-cli-help') // Let docker handle --help
.option('--build', 'Build packages before packing them into the image')
.description(
'Builds a docker image from the package, with all local deps included',
'Bundles the package into a docker image. All extra args are forwarded to docker image build',
)
.action(lazy(() => import('./backend/buildImage').then(m => m.default)));
+12
View File
@@ -48,6 +48,11 @@ type Options = {
* Defaults to ['yarn.lock', 'package.json'].
*/
files?: FileEntry[];
/**
* If set to true, the target packages are built before they are packaged into the workspace.
*/
buildDependencies?: boolean;
};
/**
@@ -68,6 +73,13 @@ export async function createDistWorkspace(
const targets = await findTargetPackages(packageNames);
if (options.buildDependencies) {
const scopeArgs = targets.flatMap(target => ['--scope', target.name]);
await run('yarn', ['lerna', 'run', ...scopeArgs, 'build'], {
cwd: paths.targetRoot,
});
}
await moveToDistWorkspace(targetDir, targets);
const files: FileEntry[] = options.files ?? ['yarn.lock', 'package.json'];
@@ -0,0 +1,11 @@
app:
baseUrl: http://localhost:3000
backend:
baseUrl: http://localhost:7000
listen:
port: 7000
cors:
origin: http://localhost:3000
methods: [GET, POST, PUT, DELETE]
credentials: true
@@ -1,6 +1,6 @@
app:
title: Scaffolded Backstage App
baseUrl: http://localhost:3000
baseUrl: http://localhost:7000
organization:
name: Acme Corporation
@@ -9,10 +9,6 @@ backend:
baseUrl: http://localhost:7000
listen:
port: 7000
cors:
origin: http://localhost:3000
methods: [GET, POST, PUT, DELETE]
credentials: true
{{#if dbTypeSqlite}}
database:
client: sqlite3
@@ -9,7 +9,7 @@
},
"scripts": {
"build": "backstage-cli backend:build",
"build-image": "backstage-cli backend:build-image example-backend",
"build-image": "backstage-cli backend:build-image --build --tag example-backend",
"start": "backstage-cli backend:dev",
"lint": "backstage-cli lint",
"test": "backstage-cli test",