├── fleet ├── simple_todos │ ├── simple-todos@1.service │ ├── simple-todos@2.service │ ├── simple-todos@3.service │ ├── simple-todos-discovery@1.service │ ├── simple-todos-discovery@2.service │ └── simple-todos-discovery@3.service ├── static │ └── dockerui.service ├── templates │ ├── fleet-ui@.service │ ├── cadvisor@.service │ ├── telescope@.service │ ├── simple-todos@.service │ └── simple-todos-discovery@.service └── cloud-config.yaml ├── docs ├── screenshot.png ├── 6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.key ├── 6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.pdf ├── 6th_Meteor_Meetup_Seoul_Dockerizing_Meteor_extra.key └── details.md ├── bin ├── docker-enter ├── deploy.sh ├── create_droplet.sh └── shell_env ├── .gitignore ├── .gitmodules └── README.md /fleet/simple_todos/simple-todos@1.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos@.service -------------------------------------------------------------------------------- /fleet/simple_todos/simple-todos@2.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos@.service -------------------------------------------------------------------------------- /fleet/simple_todos/simple-todos@3.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos@.service -------------------------------------------------------------------------------- /fleet/simple_todos/simple-todos-discovery@1.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos-discovery@.service -------------------------------------------------------------------------------- /fleet/simple_todos/simple-todos-discovery@2.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos-discovery@.service -------------------------------------------------------------------------------- /fleet/simple_todos/simple-todos-discovery@3.service: -------------------------------------------------------------------------------- 1 | ../templates/simple-todos-discovery@.service -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/HEAD/docs/screenshot.png -------------------------------------------------------------------------------- /docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/HEAD/docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.key -------------------------------------------------------------------------------- /docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/HEAD/docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor.pdf -------------------------------------------------------------------------------- /docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor_extra.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/HEAD/docs/6th_Meteor_Meetup_Seoul_Dockerizing_Meteor_extra.key -------------------------------------------------------------------------------- /bin/docker-enter: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Check for nsenter. If not found, install it 5 | boot2docker ssh '[ -f /var/lib/boot2docker/nsenter ] || docker run --rm -v /var/lib/boot2docker/:/target jpetazzo/nsenter' 6 | 7 | # Use bash if no command is specified 8 | args=$@ 9 | if [[ $# = 1 ]]; then 10 | args+=(/bin/bash) 11 | fi 12 | 13 | boot2docker ssh -t sudo /var/lib/boot2docker/docker-enter "${args[@]}" 14 | -------------------------------------------------------------------------------- /fleet/static/dockerui.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=DockerUI Service 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | User=core 8 | TimeoutStartSec=0 9 | EnvironmentFile=/etc/environment 10 | ExecStartPre=/usr/bin/docker pull davivcgarcia/dockerui 11 | ExecStartPre=-/usr/bin/docker rm dockerui 12 | ExecStart=/usr/bin/docker run --rm --name dockerui --memory="256m" -p 9000:9000 -v /var/run/docker.sock:/docker.sock davivcgarcia/dockerui -e /docker.sock 13 | ExecStop=/usr/bin/docker stop dockerui 14 | ExecStopPost=-/usr/bin/docker rm dockerui 15 | 16 | Restart=always 17 | RestartSec=10s 18 | 19 | [X-Fleet] 20 | Global=true -------------------------------------------------------------------------------- /fleet/templates/fleet-ui@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=fleet-ui 3 | After=docker.service 4 | Requires=docker.service 5 | After=etcd.service 6 | Requires=etcd.service 7 | 8 | [Service] 9 | User=core 10 | TimeoutStartSec=0 11 | EnvironmentFile=/etc/environment 12 | ExecStartPre=/usr/bin/docker pull purpleworks/fleet-ui:0.1.3 13 | ExecStartPre=-/usr/bin/docker rm fleet_ui 14 | ExecStart=/usr/bin/docker run -p 3030:3000 --name fleet_ui --memory="128m" -v /home/core/.ssh/id_rsa:/root/id_rsa purpleworks/fleet-ui:0.1.3 15 | ExecStop=/usr/bin/docker stop fleet_ui 16 | ExecStopPost=-/usr/bin/docker rm fleet_ui 17 | 18 | Restart=always 19 | RestartSec=10s 20 | 21 | [X-Fleet] 22 | Conflicts=fleet-ui.*.service 23 | -------------------------------------------------------------------------------- /fleet/templates/cadvisor@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=cAdvisor Service 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | TimeoutStartSec=10m 8 | Restart=always 9 | ExecStartPre=-/usr/bin/docker kill cadvisor 10 | ExecStartPre=-/usr/bin/docker rm -f cadvisor 11 | ExecStartPre=/usr/bin/docker pull google/cadvisor 12 | ExecStart=/usr/bin/docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=4194:4194 --name=cadvisor --net=host google/cadvisor:latest --logtostderr --port=4194 13 | ExecStop=/usr/bin/docker stop -t 2 cadvisor 14 | 15 | [X-Fleet] 16 | Conflicts=cadvisor.*.service 17 | MachineMetadata=role=kubernetes -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | jaigouk-config.yaml 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # Commenting this out is preferred by some people, see 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 27 | node_modules 28 | 29 | # Users Environment Variables 30 | .lock-wscript 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "docker-cheat-sheet"] 2 | path = docker-cheat-sheet 3 | url = https://github.com/wsargent/docker-cheat-sheet.git 4 | [submodule "simple-todos"] 5 | path = simple-todos 6 | url = https://github.com/jaigouk/simple-todos.git 7 | [submodule "fleet/nginx_lb"] 8 | path = fleet/nginx_lb 9 | url = https://github.com/jaigouk/nginx_lb.git 10 | [submodule "fleet/data-only-container"] 11 | path = fleet/data-only-container 12 | url = https://github.com/jaigouk/data-only-container.git 13 | [submodule "fleet/coreos-mongodb-cluster"] 14 | path = fleet/coreos-mongodb-cluster 15 | url = https://github.com/19hz/coreos-mongodb-cluste.git 16 | [submodule "fleet/dockerized-drone"] 17 | path = fleet/dockerized-drone 18 | url = https://github.com/jaigouk/dockerized-drone.git 19 | -------------------------------------------------------------------------------- /fleet/templates/telescope@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Telescope Service 3 | After=docker.service 4 | Requires=docker.service 5 | After=etcd.service 6 | Requires=etcd.service 7 | 8 | [Service] 9 | User=core 10 | TimeoutStartSec=0 11 | 12 | EnvironmentFile=/etc/environment 13 | 14 | ExecStartPre=-/usr/bin/docker kill telescope-%i 15 | ExecStartPre=-/usr/bin/docker rm -f telescope-%i 16 | ExecStartPre=/usr/bin/docker pull jaigouk/telescope 17 | 18 | ExecStart=/bin/bash -c '/usr/bin/docker run --name telescope-%i \ 19 | -p 3333:3000 \ 20 | --memory="512m" \ 21 | -e MONGO_URL="$(etcdctl get /mongo/replica/url)" \ 22 | -e ROOT_URL="http://127.0.0.1" \ 23 | jaigouk/telescope; \ 24 | ' 25 | 26 | ExecStop=/usr/bin/docker stop -t 3 telescope-%i 27 | 28 | Restart=always 29 | RestartSec=10s 30 | 31 | [X-Fleet] 32 | Conflicts=%p@*.service 33 | MachineOf=mongo-data@%i.service -------------------------------------------------------------------------------- /fleet/templates/simple-todos@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Simple Todos Service 3 | 4 | After=docker.service 5 | Requires=docker.service 6 | After=etcd.service 7 | Requires=etcd.service 8 | 9 | After=mongo@%i.service 10 | Requires=mongo@%i.service 11 | 12 | [Service] 13 | User=core 14 | TimeoutStartSec=0 15 | 16 | # Get CoreOS environmental variables 17 | EnvironmentFile=/etc/environment 18 | 19 | 20 | ExecStartPre=-/usr/bin/docker kill simple-todos-%i 21 | ExecStartPre=-/usr/bin/docker rm -f simple-todos-%i 22 | ExecStartPre=/usr/bin/docker pull jaigouk/simple-todos 23 | 24 | ExecStart=/bin/bash -c '/usr/bin/docker run --name simple-todos-%i \ 25 | -p 5000:5000 \ 26 | --memory="128m" \ 27 | -e MONGO_URL="$(etcdctl get /mongo/replica/url)" \ 28 | -e ROOT_URL="http://127.0.0.1" \ 29 | jaigouk/simple-todos; \ 30 | ' 31 | 32 | 33 | # Stop 34 | ExecStop=/usr/bin/docker stop -t 3 simple-todos-%i 35 | 36 | Restart=always 37 | RestartSec=10s 38 | 39 | [X-Fleet] 40 | X-Conflicts=%p@*.service 41 | Conflicts=%p@*.service 42 | MachineOf=mongo-data@%i.service -------------------------------------------------------------------------------- /fleet/cloud-config.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | coreos: 4 | etcd: 5 | addr: $private_ipv4:4001 6 | discovery: "https://discovery.etcd.io/xxxxxxxx" 7 | peer-addr: $private_ipv4:7001 8 | units: 9 | - name: etcd.service 10 | command: start 11 | - name: fleet.service 12 | command: start 13 | - name: docker-tcp.socket 14 | command: start 15 | enable: yes 16 | content: | 17 | [Unit] 18 | Description=Docker Socket for the API 19 | [Socket] 20 | ListenStream=2376 21 | BindIPv6Only=both 22 | Service=docker.service 23 | [Install] 24 | WantedBy=sockets.target 25 | - name: enable-docker-tcp.service 26 | command: start 27 | content: | 28 | [Unit] 29 | Description=Enable the Docker Socket for the API 30 | [Service] 31 | Type=oneshot 32 | ExecStart=/usr/bin/systemctl enable docker-tcp.socket 33 | write_files: 34 | - path: /home/core/.dockercfg 35 | owner: core:core 36 | permissions: 0644 37 | content: | 38 | { 39 | "https://index.docker.io/v1/": { 40 | "auth": "xXxXxXxXxXx=", 41 | "email": "username@example.com" 42 | } 43 | } -------------------------------------------------------------------------------- /fleet/templates/simple-todos-discovery@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Simple Todos etcd registration 3 | 4 | # Requirements 5 | After=etcd.service 6 | Requires=etcd.service 7 | 8 | After=simple-todos@%i.service 9 | Requires=simple-todos@%i.service 10 | BindsTo=simple-todos@%i.service 11 | 12 | [Service] 13 | TimeoutStartSec=0 14 | 15 | # Get CoreOS environmental variables 16 | EnvironmentFile=/etc/environment 17 | ExecStartPre=/bin/bash -c '/usr/bin/etcdctl set /services/meteor/${COREOS_PUBLIC_IPV4}/started $(echo $(date -u));' 18 | 19 | # Start 20 | ## Test whether service is accessible and then register useful information 21 | ExecStart=/bin/bash -c '\ 22 | while true; do \ 23 | RESULT=$(curl -Is http://${COREOS_PUBLIC_IPV4}:5000 | grep HTTP | cut -d " " -f2); \ 24 | if [ $RESULT -eq 200 ]; then \ 25 | etcdctl set /services/meteor/${COREOS_PUBLIC_IPV4} "$COREOS_PUBLIC_IPV4:5000"; \ 26 | else \ 27 | etcdctl rm /services/meteor/${COREOS_PUBLIC_IPV4} --recursive; \ 28 | fi; \ 29 | sleep 30; \ 30 | done' 31 | 32 | # Stop 33 | ExecStop=/usr/bin/etcdctl rm /services/meteor/${COREOS_PUBLIC_IPV4} --recursive 34 | 35 | Restart=always 36 | RestartSec=10s 37 | 38 | [X-Fleet] 39 | X-Conflicts=%p@*.service 40 | Conflicts=%p@*.service 41 | MachineOf=simple-todos@%i.service -------------------------------------------------------------------------------- /bin/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | USAGE="Usage: $0 [-k ssh key id] [-t digitalocean v2 token] [-o droplet name prefix] [-n number of droplets] [-e etcd token] [-s droplet size] 5 | Options: 6 | -k SSH_KEY_ID SSH KEY ID on digitalocean. you need digitalocean token to get it. 7 | -t DO_TOKEN digitalocean api v2 token that has read/write permission 8 | -o DROPLET_NAME name prefix for droplets. core => core-1, core-2, core-3 9 | -n INPUT_NUM default 3 10 | -e ETCD_TOKEN without this option, we will get one by default 11 | -s DROPLET_SIZE 512mb|1gb|2gb|4gb|8gb|16gb 12 | " 13 | 14 | while [ "$#" -gt 0 ]; do 15 | case $1 in 16 | -k) 17 | shift 1 18 | INPUT_SSH_KEY_ID=$1 19 | ;; 20 | -t) 21 | shift 1 22 | DO_TOKEN=$1 23 | echo "do token: $DO_TOKEN " 24 | ;; 25 | -o) 26 | shift 1 27 | DROPLET_NAME=$1 28 | ;; 29 | -n) 30 | shift 1 31 | INPUT_NUM=$1 32 | ;; 33 | -e) 34 | shift 1 35 | ETCD_TOKEN=$1 36 | ;; 37 | -s) 38 | shift 1 39 | DROPLET_SIZE=$1 40 | ;; 41 | --help) 42 | echo "$USAGE" 43 | exit 0 44 | ;; 45 | -h) 46 | echo "$USAGE" 47 | exit 0 48 | ;; 49 | esac 50 | shift 1 51 | done 52 | 53 | if ! echo $DROPLET_SIZE | grep -qE '512mb|1gb|2gb|4gb|8gb|16gb'; then 54 | echo 'DROPLET_SIZE must be 512mb|1gb|2gb|4gb|8gb|16gb' 55 | echo 'default 2gb' 56 | export SIZE='2gb' 57 | else 58 | export SIZE=$DROPLET_SIZE 59 | fi 60 | 61 | 62 | if [ -z "$DO_TOKEN" ]; then 63 | echo "Please input your token for Digital Ocean after -t option." 64 | echo "visit https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2#how-to-generate-a-personal-access-token" 65 | exit 1 66 | fi 67 | 68 | if (test -z "$INPUT_SSH_KEY_ID" ); then 69 | echo -n "=========================" 70 | curl -X GET -H "Authorization: Bearer $DO_TOKEN" "https://api.digitalocean.com/v2/account/keys" 71 | echo -n "=========================" 72 | echo -n "Please input your ssh key id for CoreOS..." 73 | read -s INPUT_SSH_KEY_ID 74 | export SSH_KEY_ID=$INPUT_SSH_KEY_ID 75 | else 76 | export SSH_KEY_ID=$INPUT_SSH_KEY_ID 77 | fi 78 | 79 | if [ -z "$ETCD_TOKEN" ]; then 80 | export DISCOVERY_URL=`curl -fsS -X PUT https://discovery.etcd.io/new` 81 | echo "Please SAVE your DISCOVERY_URL safely somewhere..." 82 | echo "$DISCOVERY_URL" 83 | else 84 | export DISCOVERY_URL="https://discovery.etcd.io/$ETCD_TOKEN" 85 | echo "$DISCOVERY_URL" 86 | fi 87 | 88 | if [ -z "$INPUT_NUM" ]; then 89 | export NUM_OF_DROPLETS=3 90 | else 91 | export NUM_OF_DROPLETS=$INPUT_NUM 92 | fi 93 | 94 | if [ -z "$DROPLET_NAME" ]; then 95 | DROPLET_NAME=core 96 | export DROPLET_NAME=$DROPLET_NAME 97 | fi 98 | 99 | NAME_PREFIX=$DROPLET_NAME 100 | for i in `seq $NUM_OF_DROPLETS`; do /bin/bash ./create_droplet.sh "$NAME_PREFIX-$i"; done -------------------------------------------------------------------------------- /bin/create_droplet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -n "$1" ]; then 4 | DROPLET_NAME=$1 5 | echo "will create $NUM_OF_DROPLETS of $DROPLET_NAME" 6 | else 7 | DROPLET_NAME=tcore00 8 | fi 9 | 10 | DOCKER_HUB_AUTH_PART=$(cat ~/.dockercfg| awk -F':' '{print $4}') 11 | DOCKER_HUB_AUTH_TEMP=$(echo $DOCKER_HUB_AUTH_PART | awk -F',' '{print $1}') 12 | DOCKER_HUB_AUTH=$(echo $DOCKER_HUB_AUTH_TEMP | awk -F'"' '{print $2}') 13 | DOCKER_HUB_EMAIL_PART=$(cat ~/.dockercfg| awk -F':' '{print $5}') 14 | DOCKER_HUB_EMAIL=$(echo $DOCKER_HUB_EMAIL_PART | awk -F'"' '{print $2}') 15 | 16 | # echo "==========================" 17 | # echo "check vars" 18 | # echo "DOCKER_HUB_AUTH: $DOCKER_HUB_AUTH" 19 | # echo "DOCKER_HUB_EMAIL: $DOCKER_HUB_EMAIL" 20 | # echo "DO_TOKEN: $DO_TOKEN" 21 | # echo "DROPLET_NAME: $DROPLET_NAME" 22 | # echo "SIZE: $SIZE" 23 | # echo "SSH_KEY_ID: $SSH_KEY_ID" 24 | # echo "DISCOVERY_URL: $DISCOVERY_URL" 25 | # echo "==========================" 26 | 27 | # example 28 | # https://github.com/deis/deis/blob/master/contrib/coreos/user-data.example 29 | 30 | curl -X POST "https://api.digitalocean.com/v2/droplets" \ 31 | -H "Content-Type: application/json" \ 32 | -H "Authorization: Bearer $DO_TOKEN" \ 33 | -d '{"name":"'"$DROPLET_NAME"'", 34 | "region":"nyc3", 35 | "image": "coreos-stable", 36 | "size":"'"$SIZE"'", 37 | "private_networking":true, 38 | "ssh_keys":["'"$SSH_KEY_ID"'"], 39 | "user_data": 40 | "#cloud-config 41 | --- 42 | write_files: 43 | - path: /etc/ssh/sshd_config 44 | permissions: 0600 45 | owner: root:root 46 | content: | 47 | Port 22 48 | ClientAliveInterval 180 49 | UseDNS no 50 | UsePrivilegeSeparation sandbox 51 | Subsystem sftp internal-sftp 52 | PermitRootLogin no 53 | AllowUsers core 54 | PasswordAuthentication no 55 | ChallengeResponseAuthentication no 56 | - path: /home/core/.dockercfg 57 | owner: core:core 58 | permissions: 0644 59 | content: | 60 | { 61 | \"https://index.docker.io/v1/\": { 62 | \"auth\": \"'"$DOCKER_HUB_AUTH"'\", 63 | \"email\": \"'"$DOCKER_HUB_EMAIL"'\" 64 | } 65 | } 66 | coreos: 67 | etcd: 68 | discovery: '"$DISCOVERY_URL"' 69 | addr: $private_ipv4:4001 70 | peer-addr: $private_ipv4:7001 71 | peer-election-timeout: 2000 72 | peer-heartbeat-interval: 500 73 | fleet: 74 | # allow etcd to slow down at times 75 | etcd-request-timeout: 3.0 76 | public-ip: $private_ipv4 # used for fleetctl ssh command 77 | metadata: region=nyc3,public_ip=$public_ipv4 78 | units: 79 | - name: etcd.service 80 | command: start 81 | - name: fleet.service 82 | command: start 83 | - name: sshd.socket 84 | command: restart 85 | content: | 86 | [Socket] 87 | ListenStream=22 88 | Accept=yes 89 | - name: docker-tcp.socket 90 | command: start 91 | enable: yes 92 | content: | 93 | [Unit] 94 | Description=Docker Socket for the API 95 | [Socket] 96 | ListenStream=2376 97 | BindIPv6Only=both 98 | Service=docker.service 99 | [Install] 100 | WantedBy=sockets.target 101 | - name: enable-docker-tcp.service 102 | command: start 103 | content: | 104 | [Unit] 105 | Description=Enable the Docker Socket for the API 106 | [Service] 107 | Type=oneshot 108 | ExecStart=/usr/bin/systemctl enable docker-tcp.socket"}' -------------------------------------------------------------------------------- /bin/shell_env: -------------------------------------------------------------------------------- 1 | 2 | #================================ 3 | # DOCKER 4 | #================================ 5 | 6 | 7 | docker-ip(){ 8 | boot2docker ip 2> /dev/null 9 | } 10 | # docker-enter script is in $HOME/bin 11 | 12 | # for deleting old containers and images 13 | 14 | checkitout (){ 15 | check_boot2docker=$(boot2docker status | awk '{print $1}') 16 | if [ $check_boot2docker == 'running' ];then 17 | docker ps -a | grep 'Exit' | awk '{print $1}' | xargs docker rm &> /dev/null 18 | docker images | grep '' | awk '{print $3}' | xargs docker rmi &> /dev/null 19 | else 20 | echo "boot2docker is down. boot it up!" 21 | boot2docker up 22 | fi 23 | } 24 | alias clear_docker=checkitout 25 | 26 | use-boot2docker(){ 27 | boot2docker start 28 | export DOCKER_HOST=tcp://192.168.59.104:2376 29 | export DOCKER_CERT_PATH=$HOME/.boot2docker/certs/boot2docker-vm 30 | export DOCKER_TLS_VERIFY=1 31 | BOOT2DOCKER_STATUS=$(boot2docker status) 32 | RPROMPT="%{$fg[magenta]%}[boot2docker:$BOOT2DOCKER_STATUS]%{$reset_color%}" 33 | } 34 | 35 | # export CURRENT_VM_IP=$(boot2docker ip 2> /dev/null) 36 | # alias docker-identity=docker-1.4.1-dev-identity-auth 37 | #================================ 38 | # COREOS / FLEET 39 | #================================ 40 | 41 | setup_fleet_ui(){ 42 | do_droplets=($1 $2 $3) 43 | 44 | for droplet in ${do_droplets[@]} 45 | do 46 | ssh -A core@$droplet 'rm -rf ~/.ssh/id_rsa' 47 | scp /Users/jaigouk/.docker/certs/key.pem core@$droplet:.ssh/id_rsa 48 | ssh -A core@$droplet 'chown -R core:core /home/core/.ssh; chmod 700 /home/core/.ssh; chmod 600 /home/core/.ssh/authorized_keys' 49 | done 50 | FLEETCTL_TUNNEL=$droplet:22 fleetctl destroy fleet-ui@{1..3}.service 51 | FLEETCTL_TUNNEL=$droplet:22 fleetctl destroy fleet-ui@.service 52 | FLEETCTL_TUNNEL=$droplet:22 fleetctl submit /Users/user_name/path_to_templates/fleet-ui@.service 53 | FLEETCTL_TUNNEL=$droplet:22 fleetctl start /Users/user_name/path_to_templates/fleet-ui@{1..3}.service 54 | } 55 | 56 | fleetctl-switch(){ 57 | ssh-add ~/.docker/certs/key.pem 58 | DOCKER_HOST=tcp://$1:2376 59 | export FLEETCTL_TUNNEL=$1:22 60 | #alias etcdctl="ssh -A core@$1 'etcdctl'" 61 | alias fleetctl-ssh="fleetctl ssh $(fleetctl list-machines | cut -c1-8 | sed -n 2p)" 62 | RPROMPT="%{$fg[magenta]%}[fleetctl:$1]%{$reset_color%}" 63 | } 64 | start_mongo_replica(){ 65 | CONTROL_IP=$1 66 | export FLEETCTL_TUNNEL=$CONTROL_IP:22 67 | ssh -A core@$CONTROL_IP 'etcdctl set /mongo/replica/name myreplica' 68 | FLEETCTL_TUNNEL=$1:22 fleetctl submit mongo-data@.service mongo@.service mongo-replica-config.service 69 | FLEETCTL_TUNNEL=$1:22 fleetctl start mongo-data@{1..3}.service 70 | FLEETCTL_TUNNEL=$1:22 fleetctl start mongo@{1..3}.service 71 | FLEETCTL_TUNNEL=$1:22 fleetctl start mongo-replica-config.service 72 | } 73 | destroy_mongo_replica() { 74 | CONTROL_IP=$1 75 | export FLEETCTL_TUNNEL=$CONTROL_IP:22 76 | alias etcdctl="ssh -A core@$CONTROL_IP 'etcdctl'" 77 | FLEETCTL_TUNNEL=$1:22 fleetctl destroy mongo-data@{1..3}.service 78 | FLEETCTL_TUNNEL=$1:22 fleetctl destroy mongo@{1..3}.service 79 | FLEETCTL_TUNNEL=$1:22 fleetctl destroy mongo-data@.service 80 | FLEETCTL_TUNNEL=$1:22 fleetctl destroy mongo@.service 81 | FLEETCTL_TUNNEL=$1:22 fleetctl destroy mongo-replica-config.service 82 | ssh -A core@$CONTROL_IP 'etcdctl rm /mongo/replica/url' 83 | ssh -A core@$CONTROL_IP 'etcdctl rm /mongo/replica/siteRootAdmin --recursive' 84 | ssh -A core@$CONTROL_IP 'etcdctl rm /mongo/replica/siteUserAdmin --recursive' 85 | ssh -A core@$CONTROL_IP 'etcdctl rm /mongo/replica --recursive' 86 | ssh -A core@$CONTROL_IP 'etcdctl set /mongo/replica/name myreplica' 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | zero-to-dockerized-meteor 2 | -------------- 3 | 4 | Dockerizing Meteor talk slide link at 6th Meteor Meetup Seoul 5 | 6 | [![ScreenShot](https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/master/docs/screenshot.png)](http://www.slideshare.net/jaigouk/dockerizing-meteor-6th-meteor-meetup-seoul) 7 | 8 | # Goals 9 | 10 | Full stack on Digital Ocean 11 | 12 | - [x] dockerize Meteor Apps 13 | - [x] dockerize NGINX 14 | - [x] app registration discovery for nginx load balancer(done by confd) 15 | - [ ] use vulcand instead of nginx load balancer 16 | - [ ] configure DroneCI via fleet unit file (drone_conf.toml) 17 | - [ ] continuos deployment 18 | - [ ] Ambassador pattern for mongodb replica set 19 | - [ ] dig into https://github.com/meteorhacks/cluster 20 | 21 | # Deploy steps 22 | 23 | ### STEP0) create cert files 24 | 25 | follow this [docker doc](https://docs.docker.com/articles/https/) and put them in `~/.docker/certs/key.pem` 26 | 27 | ### STEP1) Setup digitalocean 28 | ``` 29 | cd bin 30 | ./deploy.sh -n 3 -o staging -t xxx -s 4gb -k 31 | 32 | ``` 33 | 34 | usage. if you don't know or don't have digitalocean token, visit [this page](https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2#how-to-generate-a-personal-access-token). And it's ok if you don't know SSH_KEY_ID. script will show the json result if you provide digitalocean token(read + write). just copy id and paste then hit enter. 35 | 36 | ``` 37 | Usage: $0 [-k ssh key id] [-t digitalocean v2 token] [-o droplet name prefix] [-n number of droplets] [-e etcd token] [-s droplet size] 38 | 39 | Options: 40 | -k SSH_KEY_ID SSH KEY ID on digitalocean. you need digitalocean token to get it. 41 | -t DO_TOKEN digitalocean api v2 token that has read/write permission 42 | -o DROPLET_NAME name prefix for droplets. core => core-1, core-2, core-3 43 | -n INPUT_NUM default 3 44 | -e ETCD_TOKEN without this option, we will get one by default 45 | -s DROPLET_SIZE 512mb|1gb|2gb|4gb|8gb|16gb 46 | 47 | ``` 48 | 49 | ### STEP2) launch fleet services 50 | 51 | ``` 52 | source ./bin/shell_env 53 | fleetctl-switch 54 | setup_fleet_ui 55 | cd ./fleet/coreos-mongodb-cluster 56 | start_mongo_replica 57 | fleetctl start ./fleet/nginx_lb/nginx_lb.service 58 | fleetctl start ./fleet/simple_todos/* 59 | fleetctl start ./fleet/dockerized-drone/*.service 60 | ``` 61 | 62 | ### STEP3) DNS Setup (namecheap) 63 | 64 | Once the droplet is up and running you should have an IP address to work with. If you're using namecheap, go to the "All Host Records" page of namecheap's "My Account > Manage Domains > Modify Domain" section. 65 | 66 | You'll need an A record for the naked domain (the "@" one) pointing to your IP with the lowest TTL possible (namecheap caps the minimum at 60), and a wildcard for subdomains with the same info. I'd recommend redirecting www to the naked domain. 67 | 68 | It should look something like this when you're done entering your data. 69 | 70 | | HOST NAME | IP ADDRESS/URL | RECORD TYPE | MX PREF | TTL | 71 | | --- | --- | --- | --- | --- | 72 | | @ | your.ip.address.k.thx | A (Address) | n/a | 60 | 73 | | www | http://your.domain | URL Redirect (301) | n/a | 60 | 74 | | * | your.ip.address.k.thx | A (Address) | n/a | 60 | 75 | 76 | # References 77 | 78 | [Automatic Docker Deployment With Codeship](https://xivilization.net/~marek/blog/2014/10/11/automatic-docker-deployment-with-codeship/) 79 | 80 | [Codeship Blog](http://blog.codeship.com/?s=docker) 81 | 82 | [Giant swarm blog: Getting Started with Microservices using Ruby on Rails and Docker](http://blog.giantswarm.io/getting-started-with-microservices-using-ruby-on-rails-and-docker) 83 | 84 | [martinfowler: microservice-testing](http://martinfowler.com/articles/microservice-testing/) 85 | 86 | [Rainforest: Docker in Action - Development to Delivery, Part 2](https://blog.rainforestqa.com/2014-12-08-docker-in-action-from-deployment-to-delivery-part-2-continuous-integration/) -------------------------------------------------------------------------------- /docs/details.md: -------------------------------------------------------------------------------- 1 | zero-to-dockerized-meteor 2 | -------------- 3 | 4 | Dockerizing Meteor talk slide link at 6th Meteor Meetup Seoul 5 | 6 | [![ScreenShot](https://raw.githubusercontent.com/jaigouk/zero-to-dockerized-meteor-cluster/master/docs/screenshot.png)](http://www.slideshare.net/jaigouk/dockerizing-meteor-6th-meteor-meetup-seoul) 7 | 8 | ## STEP0) Prerequisites 9 | 10 | 11 | * [boot2docker](boot2docker.io) 12 | * [virtualbox](https://www.virtualbox.org/) 13 | 14 | ``` 15 | brew install fleetctl 16 | brew install etcdctl 17 | ``` 18 | 19 | 20 | * zsh_alias 21 | 22 | ``` 23 | 24 | docker-ip(){ 25 | boot2docker ip 2> /dev/null 26 | } 27 | # docker-enter script is in /Users/jaigouk/bin 28 | 29 | # for deleting old containers and images 30 | 31 | checkitout (){ 32 | check_boot2docker=$(boot2docker status | awk '{print $1}') 33 | if [ $check_boot2docker == 'running' ];then 34 | docker ps -a | grep 'Exit' | awk '{print $1}' | xargs docker rm &> /dev/null 35 | docker images | grep '' | awk '{print $3}' | xargs docker rmi &> /dev/null 36 | else 37 | echo "boot2docker is down. boot it up!" 38 | boot2docker up 39 | fi 40 | } 41 | 42 | 43 | use-boot2docker(){ 44 | boot2docker start 45 | export DOCKER_HOST=tcp:/xx.xx.xx.xx:2376 46 | export DOCKER_CERT_PATH=/Users/jaigouk/.boot2docker/certs/boot2docker-vm 47 | export DOCKER_TLS_VERIFY=1 48 | export CURRENT_VM_IP=$(boot2docker ip 2> /dev/null) 49 | RPROMPT="%{$fg[magenta]%}[boot2docker:$CURRENT_VM_IP]%{$reset_color%}" 50 | } 51 | ``` 52 | 53 | boot2docker is using sock to use docker command and certs for ssh and tls. 54 | ``` 55 | .boot2docker ❯ tree 56 | . 57 | ├── boot2docker-vm.sock 58 | ├── boot2docker.iso 59 | └── certs 60 | └── boot2docker-vm 61 | ├── ca.pem 62 | ├── cert.pem 63 | └── key.pem 64 | ``` 65 | 66 | I aliased machine to docker-machine because of os x's machine command. 67 | 68 | bin/docker-enter 69 | ``` 70 | #!/bin/bash 71 | set -e 72 | 73 | # Check for nsenter. If not found, install it 74 | boot2docker ssh '[ -f /var/lib/boot2docker/nsenter ] || docker run --rm -v /var/lib/boot2docker/:/target jpetazzo/nsenter' 75 | 76 | # Use bash if no command is specified 77 | args=$@ 78 | if [[ $# = 1 ]]; then 79 | args+=(/bin/bash) 80 | fi 81 | 82 | boot2docker ssh -t sudo /var/lib/boot2docker/docker-enter "${args[@]}" 83 | 84 | ``` 85 | 86 | For fleet 87 | ``` 88 | setup_fleet(){ 89 | do_droplets=(xx.xx.xx.xx xx.xx.xx.xx xx.xx.xx.xx) 90 | for droplet in ${do_droplets[@]} 91 | do 92 | ssh -A core@$droplet 'rm -rf ~/.ssh/id_rsa' 93 | scp /Users/name/.docker/certs/key.pem core@$droplet:.ssh/id_rsa 94 | ssh -A core@$droplet 'chown -R core:core /home/core/.ssh; chmod 700 /home/core/.ssh; chmod 600 /home/core/.ssh/authorized_keys' 95 | done 96 | fleetctl destroy fleet-ui@{1..3}.service 97 | fleetctl destroy fleet-ui@.service 98 | fleetctl submit /Users/name/path_to_fleet_file_dir/fleet-ui@.service 99 | fleetctl start /Users/name/path_to_fleet_file_dir/fleet-ui@{1..3}.service 100 | } 101 | 102 | fleetctl-switch(){ 103 | ssh-add ~/.docker/certs/key.pem 104 | export DOCKER_HOST=tcp://$1:2376 105 | export DOCKER_AUTH=identity 106 | export FLEETCTL_TUNNEL=$1:22 107 | alias etcdctl="ssh -A core@$1 'etcdctl'" 108 | alias clear_mongo="\ 109 | fleetctl destroy mongo@{1..3}.service; \ 110 | fleetctl destroy mongo-replica-config.service; \ 111 | fleetctl destroy mongo-data@{1..3}.service; \ 112 | etcdctl rm /mongo/replica/siteRootAdmin --recursive; \ 113 | etcdctl rm /mongo/replica/siteUserAdmin --recursive; \ 114 | etcdctl rm /mongo/replica --recursive; \ 115 | etcdctl set /mongo/replica/name myreplica; \ 116 | ssh -A core@$1 'etcdctl ls /mongo --recursive'; 117 | " 118 | alias fleetctl-ssh="fleetctl ssh $(fleetctl list-machines | cut -c1-8 | sed -n 2p)" 119 | RPROMPT="%{$fg[magenta]%}[fleetctl:$1]%{$reset_color%}" 120 | } 121 | 122 | ``` 123 | 124 | ## STEP1) Dockerize Meeteor App 125 | 126 | add `.dockerignore` and `dockerfile`. and create replica set by following [mongodb-replica-set](https://github.com/inlight-media/docker-mongodb-replica-set) 127 | 128 | ``` 129 | $docker build -t="inlight/mongodb-replica-set" github.com/inlight-media/docker-mongodb-replica-set 130 | 131 | $ docker run -i -t -d -p 27017:27017 -p 27018:27018 -p 27019:27019 --name mongodb inlight/mongodb-replica-set 132 | $ docker exec -it mongodb bash 133 | $ mongo 134 | > rs.initiate() 135 | > rs.add('6e8d183167b4:27018') # use token in 'me' 136 | > rs.add('6e8d183167b4:27019') 137 | > rs.status() 138 | ``` 139 | 140 | 141 | to get the ip address of the machine, type 142 | `boot2docker ip 2> /dev/null` 143 | 144 | and replica set name in the image is `dbReplicaSet` 145 | 146 | According to [mongodb doc](http://docs.mongodb.org/manual/reference/connection-string/), url format to access replica set is 147 | 148 | `mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]` 149 | 150 | so our url to access replica set we created is 151 | 152 | `mongodb://xx.xx.xx.xx:27017,xx.xx.xx.xx:27018,xx.xx.xx.xx:27019/?replicaSet=dbReplicaSet&connectTimeoutMS=300000` 153 | https://stackoverflow.com/questions/26752033/deploying-meteor-js-app-with-docker-and-phusion-passenger 154 | 155 | What's cool about etcd is that you can save key/value in it. For example, you can store mongodb url in etcd and use it like this. 156 | ``` 157 | ExecStart=/bin/bash -c '/usr/bin/docker run --name simple-todos-%i \ 158 | -p 5000:5000 \ 159 | --memory="128m" \ 160 | -e MONGO_URL="$(etcdctl get /mongo/replica/url)" \ 161 | -e ROOT_URL="http://127.0.0.1" \ 162 | jaigouk/simple-todos; \ 163 | ``` 164 | 165 | Dockerfile 166 | ``` 167 | FROM phusion/passenger-nodejs:latest 168 | 169 | RUN apt-get update 170 | RUN npm cache clean -f && npm install -g n && n 0.10.35 171 | RUN curl https://install.meteor.com/ | sh 172 | RUN npm install --silent -g forever 173 | 174 | ADD . ./meteorsrc 175 | WORKDIR /meteorsrc 176 | 177 | RUN meteor build --directory . 178 | RUN cd bundle/programs/server && npm install 179 | 180 | WORKDIR /meteorsrc/bundle/ 181 | ENV PORT 8080 182 | EXPOSE 8080 183 | 184 | RUN touch .foreverignore 185 | CMD forever --minUptime 1000 --spinSleepTime 1000 -w ./main.js 186 | ``` 187 | 188 | ``` 189 | cd to/your/project 190 | docker build -t lab80/sm_meteor . 191 | 192 | docker run --name sm_meteor -p 8080:8080 -e ROOT_URL=" http://127.0.0.1" -e MONGO_URL="mongodb:/xx.xx.xx.xx:27017,xx.xx.xx.xx:27018,xx.xx.xx.xx:27019/?replicaSet=dbReplicaSet&connectTimeoutMS=300000" lab80/sm_meteor 193 | 194 | ``` 195 | 196 | 197 | setting up autommated builds on docker hub. 198 | 199 | for submodules, add web hook as described in [docker-hub doc](http://docs.docker.com/docker-hub/builds/#github-submodules) 200 | 201 | for bitbucket, I copied deploy key from docker hub and added to submodule's bitbucket repo deplyment key in settings. 202 | 203 | or you can just `docker push lab80/sm_meteor` 204 | 205 | ## STEP2) coreos setup on digitalocean 206 | 207 | create coreos instances with private networking and following user data. 208 | Using the `coreos-ssh-import-github` field, we can import public SSH keys from a GitHub user to use as authorized keys to a server. 209 | 210 | `curl -w "\n" https://discovery.etcd.io/new` 211 | 212 | Since we are using private docker images, we need to setup coreos cluster with .dockercfg file as mentioned in [this coreos document](https://coreos.com/docs/launching-containers/building/registry-authentication/) 213 | 214 | ``` 215 | #cloud-config 216 | 217 | coreos: 218 | etcd: 219 | addr: $private_ipv4:4001 220 | discovery: "https://discovery.etcd.io/xxxxxx" 221 | peer-addr: $private_ipv4:7001 222 | units: 223 | - name: etcd.service 224 | command: start 225 | - name: fleet.service 226 | command: start 227 | write_files: 228 | - path: /home/core/.dockercfg 229 | owner: core:core 230 | permissions: 0644 231 | content: | 232 | { 233 | "https://index.docker.io/v1/": { 234 | "auth": "xXxXxXxXxXx=", 235 | "email": "username@example.com" 236 | }, 237 | "https://index.example.com": { 238 | "auth": "XxXxXxXxXxX=", 239 | "email": "username@example.com" 240 | } 241 | } 242 | ``` 243 | 244 | ``` 245 | ssh-add ~/.docker/certs/key.pem 246 | ``` 247 | 248 | When you connect to your CoreOS host, pass the -A flag to forward your user agent info so that you can connect to the other cluster members from the one you are logged into 249 | 250 | `ssh -A core@xx.xx.xx.xx` 251 | `ssh -A core@xx.xx.xx.xx` 252 | `ssh -A core@xx.xx.xx.xx` 253 | 254 | to use fleetctl you need to add fingerprint first. 255 | ``` 256 | $ ssh -A core@xx.xx.xx.xx 257 | $ FLEETCTL_TUNNEL=xx.xx.xx.xx:22 fleetctl list-machines 258 | ``` 259 | 260 | and check `fleetctl list-machines` inside of one instance. If you do not see the result of the command as followed, then you should recreate the cluster with a new etcd token. 261 | 262 | ``` 263 | core@core-1 ~ $ fleetctl list-machines 264 | MACHINE IP METADATA 265 | fd82e763... 104.xx.xx.xx.xx - 266 | ba34bcfd... 104.xx.xx.xx.xx - 267 | de856979... 104.xx.xx.xx.xx - 268 | ``` 269 | 270 | 271 | `fleetctl --endpoint http://xx.xx.xx.xx:4001 list-machines` 272 | or 273 | `fleetctl --tunnel xx.xx.xx.xx:22 list-units` 274 | 275 | 276 | ``` 277 | switch(){ 278 | export FLEETCTL_TUNNEL=$1:22 279 | export ETCDCTL_PEERS=$1:4001 280 | RPROMPT="%{$fg[magenta]%}[fleetctl:$1]%{$reset_color%}" 281 | } 282 | ``` 283 | 284 | now you can just run 285 | `fleetctl list-machines` or `etcdctl ls / --recursive` 286 | 287 | ``` 288 | cd zero-to-dockerized-meteor-cluster/fleet/simple_todos 289 | ln -s ../templates/simple-todos@.service simple-todos@1.service 290 | ln -s ../templates/simple-todos@.service simple-todos@2.service 291 | ln -s ../templates/simple-todos@.service simple-todos@3.service 292 | ln -s ../templates/simple-todos-discovery@.service simple-todos-discovery@1.service 293 | ln -s ../templates/simple-todos-discovery@.service simple-todos-discovery@2.service 294 | ln -s ../templates/simple-todos-discovery@.service simple-todos-discovery@3.service 295 | cd .. 296 | fleetctl start simple_todos/* 297 | ``` 298 | 299 | 300 | ## STEP3) MongoDB Replica Set 301 | 302 | You can save actual data in 303 | 1) a coreos dir 304 | 2) another docker container. 305 | 306 | If you want to know more about this subject, please visit my [data-only-container repo](https://github.com/jaigouk/data-only-container). For setting up replica set please visit, 307 | 308 | 1) with a coreos dir : https://github.com/jaigouk/coreos-mongodb 309 | 2) with another data container : https://github.com/19hz/coreos-mongodb-cluster 310 | 311 | Deploy 312 | 313 | ``` 314 | ssh -A core@xx.xx.xx.xxx 'etcdctl set /mongo/replica/name myReplica' 315 | fleetctl submit mongo-replica-config.service 316 | fleetctl submit mongo@.service 317 | fleetctl start mongo@{1..3}.service mongo-replica-config.service 318 | ``` 319 | 320 | Connect 321 | 322 | You can test connecting to your replica from one of your nodes as follows: 323 | ``` 324 | export SITE_ROOT_PWD=$(ssh -A core@xx.xx.xx.xx etcdctl get /mongo/replica/siteRootAdmin/pwd) 325 | export REPLICA=$(ssh -A core@xx.xx.xx.xx etcdctl get /mongo/replica/name) 326 | export FIRST_NODE=$(fleetctl list-machines --no-legend | awk '{print $2}' | head -n 1) 327 | alias remote_mongo="docker run -it --rm mongo:2.8 mongo $REPLICA/$FIRST_NODE/admin -u siteRootAdmin -p $SITE_ROOT_PWD" 328 | ``` 329 | 330 | Starting mongodb replica set 331 | 332 | ``` 333 | $ cd to_this_repo/fleet/templates 334 | $ fleetctl start mongo-data@{1..3}.service mongo@{1..3}.service mongo-replica-config.service 335 | ``` 336 | 337 | save mongo url 338 | 339 | ``` 340 | $ SITE_USR_ADMIN_PWD=$(etcdctl get /mongo/replica/siteUserAdmin/pwd 2>/dev/null || true ); \ 341 | > REPLICA_NAME=$(etcdctl get /mongo/replica/name 2>/dev/null || true ); \ 342 | > MONGO_NODES_WITH_COMMA=$(etcdctl ls /mongo/replica/nodes | xargs -I{} basename {} | xargs -I{} printf "%s," {}:27017); \ 343 | > MONGO_NODES=${MONGO_NODES_WITH_COMMA::-1}; \ 344 | > MONGODB="mongodb://siteUserAdmin:"$SITE_USR_ADMIN_PWD"@"$MONGO_NODES"/?replicaSet="$REPLICA_NAME"&connectTimeoutMS=300000"; 345 | > 346 | $ etcdctl set /mongo/replica/url $MONGODB 347 | ``` 348 | 349 | If you want to destroy and revert everything, then 350 | 351 | ``` 352 | # remove all units 353 | $ fleetctl destroy mongo@{1..3}.service 354 | $ fleetctl destroy mongo-replica-config.service 355 | # or 356 | $ fleetctl list-units --no-legend | awk '{print $1}' | xargs -I{} fleetctl destroy {} 357 | 358 | # clean directories 359 | $ fleetctl list-machines --fields="machine" --full --no-legend | xargs -I{} fleetctl ssh {} "sudo rm -rf /var/mongo/*" 360 | 361 | (from inside one of the nodes) 362 | $ etcdctl rm /mongo/replica/key 363 | $ etcdctl rm --recursive /mongo/replica/siteRootAdmin 364 | $ etcdctl rm --recursive /mongo/replica/siteUserAdmin 365 | $ etcdctl rm --recursive /mongo/replica/nodes 366 | 367 | ``` 368 | 369 | 370 | 371 | ## STEP4) RUN YOUR METEOR APP 372 | 373 | Starting services 374 | ``` 375 | $ cd to_this_repo/fleet/templates 376 | $ fleetctl start simple-todos@{1..3}.service 377 | $ fleetctl start telescope@{1..3}.service 378 | ``` 379 | 380 | 381 | you can run commands like these. 382 | ``` 383 | fleetctl submit telescope@{1..3}.service && fleetctl start telescope@{1..3}.service 384 | fleetctl list-units 385 | fleetctl status telescope@{1..3}.service 386 | fleetctl journal -f telescope@{1..3}.service 387 | fleetctl stop telescope@{1..3}.service 388 | fleetctl destroy telescope@{1..3}.service 389 | ``` 390 | 391 | Fleet-ui example 392 | 393 | ``` 394 | setup_fleet_ui(){ 395 | do_droplets=(xx.xx.xx.xx xx.xx.xx.xx xx.xx.xx.xx) 396 | for droplet in ${do_droplets[@]} 397 | do 398 | ssh -A core@$droplet 'rm -rf ~/.ssh/id_rsa' 399 | scp /Users/jaigouk/.docker/certs/key.pem core@$droplet:.ssh/id_rsa 400 | ssh -A core@$droplet 'chown -R core:core /home/core/.ssh; chmod 700 /home/core/.ssh; chmod 600 /home/core/.ssh/authorized_keys' 401 | done 402 | fleetctl destroy fleet-ui@{1..3}.service 403 | fleetctl destroy fleet-ui@.service 404 | fleetctl start /Users/your_name/path_to_fleet_templates/fleet-ui@{1..3}.service 405 | } 406 | 407 | ``` 408 | 409 | 410 | 411 | # References 412 | 413 | * [Runnning Heapster on CoreOS](https://github.com/GoogleCloudPlatform/heapster/tree/master/clusters/coreos) Heapster enables cluster monitoring in a CoreOS cluster using cAdvisor. 414 | 415 | * [mongodb replica on coreos by auth0](https://github.com/auth0/coreos-mongodb) 416 | 417 | * [confd](https://github.com/kelseyhightower/confd)is specifically crafted to watch distributed key-value stores for changes. It is run from within a Docker container and is used to trigger configuration modifications and service reloads. 418 | 419 | * [10 Things You Should Know About Running MongoDB At Scale](http://highscalability.com/blog/2014/3/5/10-things-you-should-know-about-running-mongodb-at-scale.html) 420 | 421 | * [Deploying Docker Containers on CoreOS Using Fleet](http://seanmcgary.com/posts/deploying-docker-containers-on-coreos-using-fleet) 422 | 423 | * [Zero Downtime Frontend Deploys with Vulcand on CoreOS](https://coreos.com/blog/zero-downtime-frontend-deploys-vulcand/) 424 | 425 | * [Getting Started with CoreOS (digitalocean tutorial)](https://www.digitalocean.com/community/tutorial_series/getting-started-with-coreos-2) 426 | 427 | * [How to correctly configure CoreOS iptables on Vultr](https://masato.github.io/2014/11/07/how-to-correctly-coreos-iptables-on-vultr/) --------------------------------------------------------------------------------