Commit d80be5dd authored by O'Reilly Media, Inc.'s avatar O'Reilly Media, Inc.

Initial commit

parents
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
\f0\fs24 \cf0 No work files for this lesson...}
\ No newline at end of file
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
\f0\fs24 \cf0 No work files for this lesson...}
\ No newline at end of file
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
\f0\fs24 \cf0 No work files for this lesson...}
\ No newline at end of file
FROM iojs:2.2-slim
WORKDIR /src
ADD package.json /src/
RUN npm install
ADD . /src/
EXPOSE 3000
CMD /usr/local/bin/iojs /src/index.js
## Simple NodeJS app
docker run --rm -ti -p 3000:3000 -e INSTANCE=instance1 -e HOST=myhost rosskukulinski/nodeapp1
var http = require('http');
var os = require("os");
var instance = process.env.INSTANCE || 'unknown instance';
var host = os.hostname();
var app = http.createServer(function (req, res) {
console.log('Request from ', req.connection.remoteAddress);
res.end('Hello from ' + instance + ' running on ' + host + '\n');
});
app.listen(3000, function() {
console.log('listening on port 3000');
});
{
"name": "docker-node-app",
"version": "1.0.0",
"description": "Simple dockerized nodejs application",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ross Kukulinski <ross@kukulinski.com>",
"license": "MIT",
"dependencies": {
}
}
[Unit]
Description=Simple Node App v2 %i
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill nodeapp-v2-%i
ExecStartPre=-/usr/bin/docker rm nodeapp-v2-%i
ExecStartPre=/usr/bin/docker pull rosskukulinski/nodeapp1
ExecStart=/usr/bin/docker run \
--name nodeapp-v2-%i \
--rm \
-p 3000:3000 \
-e INSTANCE=%i \
-h %H \
rosskukulinski/nodeapp1
ExecStop=-/usr/bin/docker rm -f nodeapp-v2-%i
[X-Fleet]
Conflicts=nodeapp-v2@*.service
[Unit]
Description=Simple Node App %i
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill nodeapp-%i
ExecStartPre=-/usr/bin/docker rm nodeapp-%i
ExecStartPre=/usr/bin/docker pull rosskukulinski/nodeapp1
ExecStart=/usr/bin/docker run \
--name nodeapp-%i \
--rm \
-p 3000:3000 \
-e INSTANCE=%i \
rosskukulinski/nodeapp1
ExecStop=-/usr/bin/docker rm -f nodeapp-%i
[X-Fleet]
Conflicts=nodeapp@*.service
# How to Contribute
CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via
GitHub pull requests. This document outlines some of the conventions on
development workflow, commit message formatting, contact points and other
resources to make it easier to get your contribution accepted.
# Certificate of Origin
By contributing to this project you agree to the Developer Certificate of
Origin (DCO). This document was created by the Linux Kernel community and is a
simple statement that you, as a contributor, have the legal right to make the
contribution. See the [DCO](DCO) file for details.
# Email and Chat
The project currently uses the general CoreOS email list and IRC channel:
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
are very busy and read the mailing lists.
## Getting Started
- Fork the repository on GitHub
- Read the [README](README.md) for build and test instructions
- Play with the project, submit bugs, submit patches!
## Contribution Flow
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where you want to base your work (usually master).
- Make commits of logical units.
- Make sure your commit messages are in the proper format (see below).
- Push your changes to a topic branch in your fork of the repository.
- Make sure the tests pass, and add any new tests as appropriate.
- Submit a pull request to the original repository.
Thanks for your contributions!
### Format of the Commit Message
We follow a rough convention for commit messages that is designed to answer two
questions: what changed and why. The subject line should feature the what and
the body of the commit should describe the why.
```
scripts: add the test-cluster command
this uses tmux to setup a test cluster that you can easily kill and
start for debugging.
Fixes #38
```
The format can be described more formally as follows:
```
<subsystem>: <what changed>
<BLANK LINE>
<why this change was made>
<BLANK LINE>
<footer>
```
The first line is the subject and should be no longer than 70 characters, the
second line is always blank, and other lines should be wrapped at 80 characters.
This allows the message to be easier to read on GitHub as well as in various
git tools.
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
Jon Boulle <jonathan.boulle@coreos.com> (@jonboulle)
Brian Waldon <brian.waldon@coreos.com> (@bcwaldon)
CoreOS Project
Copyright 2014 CoreOS, Inc
This product includes software developed at CoreOS, Inc.
(http://www.coreos.com/).
# -*- mode: ruby -*-
# # vi: set ft=ruby :
require 'fileutils'
Vagrant.require_version ">= 1.6.0"
CLOUD_CONFIG_PATH = File.join(File.dirname(__FILE__), "user-data")
CONFIG = File.join(File.dirname(__FILE__), "config.rb")
# Defaults for config options defined in CONFIG
$num_instances = 1
$instance_name_prefix = "core"
$update_channel = "alpha"
$enable_serial_logging = false
$share_home = false
$vm_gui = false
$vm_memory = 1024
$vm_cpus = 1
$shared_folders = {}
$forwarded_ports = {}
# Attempt to apply the deprecated environment variable NUM_INSTANCES to
# $num_instances while allowing config.rb to override it
if ENV["NUM_INSTANCES"].to_i > 0 && ENV["NUM_INSTANCES"]
$num_instances = ENV["NUM_INSTANCES"].to_i
end
if File.exist?(CONFIG)
require CONFIG
end
# Use old vb_xxx config variables when set
def vm_gui
$vb_gui.nil? ? $vm_gui : $vb_gui
end
def vm_memory
$vb_memory.nil? ? $vm_memory : $vb_memory
end
def vm_cpus
$vb_cpus.nil? ? $vm_cpus : $vb_cpus
end
Vagrant.configure("2") do |config|
# always use Vagrants insecure key
config.ssh.insert_key = false
config.vm.box = "coreos-%s" % $update_channel
config.vm.box_version = ">= 308.0.1"
config.vm.box_url = "http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant.json" % $update_channel
["vmware_fusion", "vmware_workstation"].each do |vmware|
config.vm.provider vmware do |v, override|
override.vm.box_url = "http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant_vmware_fusion.json" % $update_channel
end
end
config.vm.provider :virtualbox do |v|
# On VirtualBox, we don't have guest additions or a functional vboxsf
# in CoreOS, so tell Vagrant that so it can be smarter.
v.check_guest_additions = false
v.functional_vboxsf = false
end
# plugin conflict
if Vagrant.has_plugin?("vagrant-vbguest") then
config.vbguest.auto_update = false
end
(1..$num_instances).each do |i|
config.vm.define vm_name = "%s-%02d" % [$instance_name_prefix, i] do |config|
config.vm.hostname = vm_name
if $enable_serial_logging
logdir = File.join(File.dirname(__FILE__), "log")
FileUtils.mkdir_p(logdir)
serialFile = File.join(logdir, "%s-serial.txt" % vm_name)
FileUtils.touch(serialFile)
["vmware_fusion", "vmware_workstation"].each do |vmware|
config.vm.provider vmware do |v, override|
v.vmx["serial0.present"] = "TRUE"
v.vmx["serial0.fileType"] = "file"
v.vmx["serial0.fileName"] = serialFile
v.vmx["serial0.tryNoRxLoss"] = "FALSE"
end
end
config.vm.provider :virtualbox do |vb, override|
vb.customize ["modifyvm", :id, "--uart1", "0x3F8", "4"]
vb.customize ["modifyvm", :id, "--uartmode1", serialFile]
end
end
if $expose_docker_tcp
config.vm.network "forwarded_port", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true
end
$forwarded_ports.each do |guest, host|
config.vm.network "forwarded_port", guest: guest, host: host, auto_correct: true
end
["vmware_fusion", "vmware_workstation"].each do |vmware|
config.vm.provider vmware do |v|
v.gui = vm_gui
v.vmx['memsize'] = vm_memory
v.vmx['numvcpus'] = vm_cpus
end
end
config.vm.provider :virtualbox do |vb|
vb.gui = vm_gui
vb.memory = vm_memory
vb.cpus = vm_cpus
end
ip = "172.19.8.#{i+100}" # RHK Document
config.vm.network :private_network, ip: ip
# Uncomment below to enable NFS for sharing the host machine into the coreos-vagrant VM.
#config.vm.synced_folder ".", "/home/core/share", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp']
$shared_folders.each_with_index do |(host_folder, guest_folder), index|
config.vm.synced_folder host_folder.to_s, guest_folder.to_s, id: "core-share%02d" % index, nfs: true, mount_options: ['nolock,vers=3,udp']
end
if $share_home
config.vm.synced_folder ENV['HOME'], ENV['HOME'], id: "home", :nfs => true, :mount_options => ['nolock,vers=3,udp']
end
if File.exist?(CLOUD_CONFIG_PATH)
config.vm.provision :file, :source => "#{CLOUD_CONFIG_PATH}", :destination => "/tmp/vagrantfile-user-data"
config.vm.provision :shell, :inline => "mv /tmp/vagrantfile-user-data /var/lib/coreos-vagrant/", :privileged => true
end
end
end
end
# Size of the CoreOS cluster created by Vagrant
$num_instances=3
# Used to fetch a new discovery token for a cluster of size $num_instances
$new_discovery_url="https://discovery.etcd.io/new?size=#{$num_instances}"
# To automatically replace the discovery token on 'vagrant up', uncomment
# the lines below:
#
if File.exists?('user-data') && ARGV[0].eql?('up')
require 'open-uri'
require 'yaml'
token = open($new_discovery_url).read
data = YAML.load(IO.readlines('user-data')[1..-1].join)
if data['coreos'].key? 'etcd'
data['coreos']['etcd']['discovery'] = token
end
if data['coreos'].key? 'etcd2'
data['coreos']['etcd2']['discovery'] = token
end
yaml = YAML.dump(data)
File.open('user-data', 'w') { |file| file.write("#cloud-config\n\n#{yaml}") }
end
#
#
# coreos-vagrant is configured through a series of configuration
# options (global ruby variables) which are detailed below. To modify
# these options, first copy this file to "config.rb". Then simply
# uncomment the necessary lines, leaving the $, and replace everything
# after the equals sign..
# Change basename of the VM
# The default value is "core", which results in VMs named starting with
# "core-01" through to "core-${num_instances}".
#$instance_name_prefix="core"
# Official CoreOS channel from which updates should be downloaded
$update_channel='stable'
# Log the serial consoles of CoreOS VMs to log/
# Enable by setting value to true, disable with false
# WARNING: Serial logging is known to result in extremely high CPU usage with
# VirtualBox, so should only be used in debugging situations
#$enable_serial_logging=false
# Enable port forwarding of Docker TCP socket
# Set to the TCP port you want exposed on the *host* machine, default is 2375
# If 2375 is used, Vagrant will auto-increment (e.g. in the case of $num_instances > 1)
# You can then use the docker tool locally by setting the following env var:
# export DOCKER_HOST='tcp://127.0.0.1:2375'
#$expose_docker_tcp=2375
# Enable NFS sharing of your home directory ($HOME) to CoreOS
# It will be mounted at the same path in the VM as on the host.
# Example: /Users/foobar -> /Users/foobar
#$share_home=false
# Customize VMs
#$vm_gui = false
#$vm_memory = 1024
#$vm_cpus = 1
# Share additional folders to the CoreOS VMs
# For example,
# $shared_folders = {'/path/on/host' => '/path/on/guest', '/home/foo/app' => '/app'}
# or, to map host folders to guest folders of the same name,
# $shared_folders = Hash[*['/home/foo/app1', '/home/foo/app2'].map{|d| [d, d]}.flatten]
#$shared_folders = {}
# Enable port forwarding from guest(s) to host machine, syntax is: { 80 => 8080 }, auto correction is enabled by default.
$forwarded_ports = {8080 => 8080, 28015 => 28015, 4001 => 4001}
#cloud-config
---
coreos:
etcd:
addr: $public_ipv4:4001
peer-addr: $public_ipv4:7001
discovery: https://discovery.etcd.io/fb5398bed52a09c70ba7facc41a3f8d1
etcd2:
advertise-client-urls: http://$public_ipv4:2379
initial-advertise-peer-urls: http://$private_ipv4:2380
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
listen-peer-urls: http://$private_ipv4:2380,http://$private_ipv4:7001
discovery: https://discovery.etcd.io/fb5398bed52a09c70ba7facc41a3f8d1
fleet:
public-ip: $public_ipv4
flannel:
interface: $public_ipv4
units:
- name: etcd2.service
command: start
- name: fleet.service
command: start
- name: docker-tcp.socket
command: start
enable: true
content: |
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=2375
Service=docker.service
BindIPv6Only=both
[Install]
WantedBy=sockets.target
[Unit]
Description=Hello Fleet Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill hello-fleet
ExecStartPre=-/usr/bin/docker rm hello-fleet
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name hello-fleet busybox /bin/sh -c "while true; do echo Hello Fleet; sleep 1; done"
ExecStop=-/usr/bin/docker rm -f hello-fleet
[Unit]
Description=hellofleet2 Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name %p-%i busybox /bin/sh -c "while true; do echo Hello from %p-%i running on %H; sleep 1; done"
ExecStop=-/usr/bin/docker rm -f %p-%i
[X-Fleet]
Conflicts=hellofleet2@*.service
[Unit]
Description=Global Hello Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill global-hello
ExecStartPre=-/usr/bin/docker rm global-hello
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name global-hello busybox /bin/sh -c "while true; do echo Hello global-hello; sleep 1; done"
ExecStop=-/usr/bin/docker rm -f global-hello
[X-Fleet]
Global=true
[Unit]
Description=%n Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name %p-%i busybox /bin/sh -c "while true; do echo Hello from %p-%i running on %H; sleep 1; done"
ExecStop=-/usr/bin/docker rm -f %p-%i
[Install]
WantedBy=multi-user.target
[Unit]
Description=Hello World Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill hello-world
ExecStartPre=-/usr/bin/docker rm hello-world
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name hello-world busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done"
ExecStop=-/usr/bin/docker rm -f hello-world
[Install]
WantedBy=multi-user.target
FROM haproxy:1.5
MAINTAINER Ross Kukulinski "ross@getyodlr.com"
RUN apt-get -yqq update && apt-get -yqq install curl
# Install confd
RUN cd /usr/local/bin \
&& curl -L https://github.com/kelseyhightower/confd/releases/download/v0.9.0/confd-0.9.0-linux-amd64 -o confd \
&& chmod +x confd
RUN rm -rf /etc/haproxy/haproxy.cfg
ADD haproxy.toml /etc/confd/conf.d/haproxy.toml
ADD templates/haproxy.tmpl /etc/confd/templates/haproxy.tmpl
ADD confd-watch /usr/local/bin/confd-watch
RUN chmod +x /usr/local/bin/confd-watch
RUN mkdir /etc/haproxy/
EXPOSE 80
CMD /usr/local/bin/confd-watch
#!/bin/bash
set -eo pipefail
export ETCD_PORT=${ETCD_PORT:-4001}
export HOST_IP=${HOST_IP:-172.17.42.1}
export ETCD=$HOST_IP:$ETCD_PORT
echo "[haproxy] booting container. ETCD: $ETCD."
# Try to make initial configuration every 5 seconds until successful
until confd -onetime --log-level debug -node $ETCD -config-file /etc/confd/conf.d/haproxy.toml; do
echo "[haproxy] waiting for confd to create initial haproxy configuration."
sleep 5
done
# Put a continual polling `confd` process into the background to watch
# for changes every 10 seconds
confd -interval 10 --log-level debug -node $ETCD -config-file /etc/confd/conf.d/haproxy.toml &
echo "[haproxy] confd is now monitoring etcd for changes..."
# Start the haproxy service using the generated config
echo "[haproxy] starting haproxy service..."
/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid
# Loop forever to continue running
while true ; do sleep 5 ; done
[Unit]
Description=haproxy Proxy
Requires=docker.service
After=docker.service
After=etcd2.service
Requires=etcd2.service
[Service]
EnvironmentFile=/etc/environment
User=core
Restart=always
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill %p-%i
ExecStartPre=-/usr/bin/docker rm %p-%i
ExecStartPre=-/usr/bin/etcdctl mkdir /services/todo
ExecStartPre=-/usr/bin/docker pull rosskukulinski/haproxy-proxy
ExecStart=/usr/bin/docker run --name %p-%i \
-h %H \
-p ${COREOS_PUBLIC_IP}:80:80 \