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

Add docker to yeoman generator #200

Merged
merged 5 commits into from
May 25, 2016
Merged
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
17 changes: 15 additions & 2 deletions packages/generator-react-server/generators/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ module.exports = yeoman.Base.extend({
name: 'name',
message: 'What would you like to call your app?',
default: this.appname
}, {
type: 'confirm',
name: 'dockerCfg',
message: 'Do you want to generate a Docker file and Docker Compose file?',
default: false
}];

return this.prompt(prompts).then(function (props) {
Expand All @@ -23,6 +28,7 @@ module.exports = yeoman.Base.extend({

writing: function () {
var _this = this;

[
'_babelrc',
'_gitignore'
Expand All @@ -35,13 +41,20 @@ module.exports = yeoman.Base.extend({
);
});

[
let files = [
'hello-world-page.js',
'hello-world.js',
'package.json',
'README.md',
'routes.js'
].forEach(function (filename) {
];

if (this.props.dockerCfg) {
files.push('Dockerfile');
files.push('docker-compose.yml');
}

files.forEach(function (filename) {
_this.fs.copyTpl(
_this.templatePath(filename),
_this.destinationPath(filename),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM node:slim

EXPOSE 3000
ENV NODE_ENV=docker-dev
VOLUME /www
51 changes: 49 additions & 2 deletions packages/generator-react-server/generators/app/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,62 @@ Very simple example project for `react-server` which only shows server rendering

To start in development mode:

```
```shell
npm start
```

Then go to [localhost:3000](http://localhost:3000/). You will see a simple page that pre-renders and that is interactive on load. It also will include hot reloading of React components in their own file.

If you want to optimize the client code at the expense of startup time, type `NODE_ENV=production npm start`. You can also use any of [the other arguments for react-server-cli](../../react-server-cli#setting-options-manually) after `--`. For example:

```
```shell
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. Nice to have syntax coloring on these.

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍 Thanks for adding this!

# start in dev mode on port 4000
npm start -- --port=4000
```

# Developing using Docker and Docker Compose

These steps assume you are familiar with docker and already have it installed. Some basics:

1. Download [Docker Toolbox](https://www.docker.com/products/docker-toolbox) and install it.
2. Start `docker quick start shell`
3. Navigate to where you generated the project
4. Add a configuration to set the `host` option to the ip given by `docker-machine ip`. An example configuration might be like:
```json
{
"port": "3000",
"env": {
"docker": {
"host": "Your ip from `docker-machine ip` here"
},
Copy link
Contributor

@gigabo gigabo May 22, 2016

Choose a reason for hiding this comment

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

This is cool. Nice use of environment configuration.

Thanks for the added documentation. Clears it right up for me.

"staging": {
"port": "3000"
},
"production": {
"port": "80"
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Just occurred to me that we should probably generate this config. #203

```
5. Now that your system is ready to go, start the containers:
```shell
docker-compose build --pull
docker-compose up
```

The containers will now be running. At any time, press ctrl+c to stop them.

To clean up, run the following commands:

```shell
docker-compose stop
docker-compose rm --all
docker volume ls # and get the name of the volume ending in react_server_node_modules
docker volume rm _react_server_node_modules # this name will be different depending on the name of the project
```

The configuration included stores the node_modules directory in a "named volume". This is a special
persistent data-store that Docker uses to keep around the node_modules directory so that they don't have to
be built on each run of the container. If you need to get into the container in order to investigate what
is in the volume, you can run `docker-compose exec react_server bash` which will open a shell in the
container. Be aware that the exec functionality doesn't exist in Windows (as of this writing).
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '2'
services:
react_server: # The label of the service
build: . # The location of the Dockerfile to build
volumes: # Files to share with the container and the host
- .:/www # Share the project in /www in the container
- react_server_node_modules:/www/node_modules # A special volume so that OS specific node_modules are built correctly
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, thanks for renaming the volume, too. Didn't even catch that one.

working_dir: /www # The location all commands should run from
environment:
NODE_ENV: 'docker' # Set the NODE_ENV environment variable
command: /bin/bash -c "npm install && npm start" # The command to run in when the container starts
ports: # Ports to expose to your host
Copy link
Contributor

Choose a reason for hiding this comment

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

All these comments are really helpful!

- '3000:3000'
- '3001:3001'
# An example database
# my_db:
# image: rethinkdb:latest
# You can reference the db/service by using the dns name `my_db` and docker will do the rest

# Volume to store separate from the container runtime and host
volumes:
react_server_node_modules:
27 changes: 24 additions & 3 deletions packages/generator-react-server/test/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import path from 'path';
import test from 'ava';
import helpers from 'yeoman-test';

test('generator-react-server:app creates files', async t => {
test('generator-react-server:app creates default files', async t => {
let testDir;
await helpers.run(path.join(__dirname, '../generators/app'))
.inTmpDir(dir => {
testDir = dir;
})
.withPrompts({name: 'foo'})
.withPrompts({name: 'foo', dockerCfg: false})
.toPromise();
t.true(await exists('.babelrc', testDir));
t.true(await exists('.gitignore', testDir));
Expand All @@ -19,6 +19,27 @@ test('generator-react-server:app creates files', async t => {
t.true(await exists('package.json', testDir));
t.true(await exists('README.md', testDir));
t.true(await exists('routes.js', testDir));
t.false(await exists('Dockerfile', testDir));
t.false(await exists('docker-compose.yml', testDir));
});

test('generator-react-server:app creates docker files', async t => {
let testDir;
await helpers.run(path.join(__dirname, '../generators/app'))
.inTmpDir(dir => {
testDir = dir;
})
.withPrompts({name: 'foo', dockerCfg: true})
.toPromise();
t.true(await exists('.babelrc', testDir));
t.true(await exists('.gitignore', testDir));
t.true(await exists('hello-world-page.js', testDir));
t.true(await exists('hello-world.js', testDir));
t.true(await exists('package.json', testDir));
t.true(await exists('README.md', testDir));
t.true(await exists('routes.js', testDir));
t.true(await exists('Dockerfile', testDir));
t.true(await exists('docker-compose.yml', testDir));
});

test('generator-react-server:app passes the test target', async t => {
Expand All @@ -27,7 +48,7 @@ test('generator-react-server:app passes the test target', async t => {
.inTmpDir(dir => {
testDir = dir;
})
.withPrompts({name: 'foo'})
.withPrompts({name: 'foo', dockerCfg: false})
.toPromise();
await installDeps();
t.true(await runsSuccessfully('npm test'));
Expand Down