├── jenkins
├── data
│ └── .git_keep
├── jobs
│ └── outyet
│ │ └── config.xml
└── docker
│ └── Dockerfile
├── postgres
└── data
│ └── .git_keep
├── registry
├── data
│ └── .git_keep
├── htpasswd
├── certs
│ ├── README.md
│ ├── san.cnf
│ ├── domain.crt
│ └── domain.key
└── config.yaml
├── README.md
├── outyet
├── go.mod
├── README.md
├── docker-compose.yaml
├── Dockerfile.single
├── Dockerfile
├── Dockerfile.minimal
├── main_test.go
└── main.go
├── terraform
├── data.tf
├── files
│ ├── startup_options.conf
│ └── daemon.json
├── key-pairs.tf
├── bin
│ ├── local-ip.sh
│ ├── ssh_server.sh
│ ├── setup_workers.sh
│ ├── setup_managers.sh
│ ├── self_healing.sh
│ └── ip_vars.sh
├── outputs.tf
├── variables.tf
├── security-group.tf
├── README.md
└── app-instances.tf
├── .gitignore
├── scripts
├── docker-workshop
│ ├── clean-jenkins-data.sh
│ ├── clean-jenkins-data.ps1
│ ├── clean-all-data.sh
│ └── clean-all-data.ps1
└── class-docker-cicd
│ ├── clean-jenkins-data.sh
│ ├── clean-jenkins-data.ps1
│ ├── clean-all-data.sh
│ └── clean-all-data.ps1
├── gogs
└── conf
│ └── app.ini
└── compose
└── docker-compose.yaml
/jenkins/data/.git_keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/postgres/data/.git_keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/registry/data/.git_keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Docker CI/CD class
2 |
--------------------------------------------------------------------------------
/outyet/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/spkane/outyet
2 |
3 | go 1.18
4 |
--------------------------------------------------------------------------------
/terraform/data.tf:
--------------------------------------------------------------------------------
1 | data "aws_vpc" "default" {
2 | default = true
3 | }
4 |
--------------------------------------------------------------------------------
/registry/htpasswd:
--------------------------------------------------------------------------------
1 | myuser:$2y$05$biU9Wlzj6YwrPRtL4uZlG.DvKLfbpfFpYAxBv.g9yJVQzHXv6C//y
2 |
--------------------------------------------------------------------------------
/terraform/files/startup_options.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | ExecStart=
3 | ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375
4 |
--------------------------------------------------------------------------------
/terraform/files/daemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "runtimes": {
3 | "runsc": {
4 | "path": "/usr/local/bin/runsc"
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/terraform/key-pairs.tf:
--------------------------------------------------------------------------------
1 | resource "aws_key_pair" "deployer" {
2 | key_name = "trainer_sean_kane"
3 | public_key = file(var.ssh_public_key_path)
4 | }
5 |
--------------------------------------------------------------------------------
/terraform/bin/local-ip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | #ifconfig.me returns the ipv4 address instead of an ipv6 address
6 | echo "{\"public_ip\":\"$(curl -sL4 ifconfig.me)\"}"
7 |
--------------------------------------------------------------------------------
/terraform/outputs.tf:
--------------------------------------------------------------------------------
1 | output "manager-ips" {
2 | value = join(",", aws_instance.manager.*.public_ip)
3 | }
4 |
5 | output "worker-ips" {
6 | value = join(",", aws_instance.worker.*.public_ip)
7 | }
8 |
--------------------------------------------------------------------------------
/registry/certs/README.md:
--------------------------------------------------------------------------------
1 | openssl req -out sslcert.csr -newkey rsa:2048 -nodes -keyout domain.key -config san.cnf
2 | openssl req -noout -text -in sslcert.csr | grep DNS
3 | openssl x509 -signkey domain.key -in sslcert.csr -req -days 3650 -out domain.crt
4 |
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | sslcert.csr
2 | .env
3 | outyet/outyet
4 | postgres/data/*
5 | registry/data/*
6 | jenkins/data/*
7 | terraform/terraform.tfstate*
8 | terraform/.terraform
9 | terraform/.terraform.lock.hcl
10 | !postgres/data/.git_keep
11 | !registry/data/.git_keep
12 | !jenkins/data/.git_keep
13 |
14 |
--------------------------------------------------------------------------------
/outyet/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 | Build Status: [](http://127.0.0.1:10091/job/outyet/)
4 |
5 | Forked from: [github.com/golang/example](https://github.com/golang/example)
6 |
7 | ## Build
8 |
9 | - `docker image build .`
10 |
11 |
--------------------------------------------------------------------------------
/terraform/bin/ssh_server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -u
5 |
6 | source ./bin/ip_vars.sh 1> /dev/null
7 |
8 | ssh -o "IdentitiesOnly=yes" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/oreilly_aws ubuntu@${primary_manager_ip}
9 |
10 | echo
11 | echo "Test your setup with:"
12 | echo
13 | echo "docker -H ${primary_manager_ip}:2375 node list"
14 | echo
15 |
--------------------------------------------------------------------------------
/outyet/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | outyet:
3 | #build:
4 | # context: .
5 | # We are just going to use the upstream image for demos
6 | # however, it would be more accurate to build it from the local code.
7 | image: spkane/outyet:latest
8 | ports:
9 | - "10088:8080"
10 | networks:
11 | - my-net
12 | networks:
13 | my-net:
14 | driver: bridge
15 |
--------------------------------------------------------------------------------
/terraform/bin/setup_workers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -u
5 |
6 | source ./bin/ip_vars.sh 1> /dev/null
7 |
8 | for i in "${worker_ips[@]}"
9 | do
10 | ssh -o "IdentitiesOnly=yes" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o "BatchMode=yes" -i ~/.ssh/oreilly_aws ubuntu@${i} "sudo docker swarm join --token ${SWARM_WORKER_TOKEN} ${primary_manager_ip}:2377"
11 | done
12 |
13 | echo
14 | echo "Test your setup with:"
15 | echo
16 | echo "docker -H ${primary_manager_ip}:2375 node list"
17 | echo
18 |
--------------------------------------------------------------------------------
/scripts/docker-workshop/clean-jenkins-data.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BASE="${HOME}/docker-workshop"
4 |
5 | echo "This will reset all the Jenkins data under ${BASE} !!!"
6 | echo
7 | echo "Are you sure this is what you want to do?"
8 | read -p "You must type 'yes' to confirm: " -r
9 | echo
10 | if [[ $REPLY == "yes" ]]; then
11 | rm -rf ${BASE}/layout/jenkins/data/*
12 | rm -rf ${BASE}/layout/jenkins/data/.groovy
13 | rm -rf ${BASE}/layout/jenkins/data/.java
14 | echo "completed"
15 | else
16 | echo "aborted"
17 | fi
18 |
19 |
--------------------------------------------------------------------------------
/outyet/Dockerfile.single:
--------------------------------------------------------------------------------
1 | FROM golang:1.22.0 AS builder
2 | # Build Image
3 |
4 | COPY . /go/src/outyet
5 | WORKDIR /go/src/outyet
6 |
7 | ENV CGO_ENABLED=0
8 | ENV GOOS=linux
9 |
10 | RUN go get -v -d && \
11 | go install -v && \
12 | go test -v && \
13 | go build -ldflags "-s" -a -installsuffix cgo -o outyet .
14 |
15 | RUN apt-get install -y ca-certificates
16 |
17 | WORKDIR /
18 | RUN cp /go/src/outyet/outyet .
19 |
20 | EXPOSE 8080
21 |
22 | CMD ["/outyet", "-version", "1.9.4", "-poll", "600s", "-http", ":8080"]
23 |
--------------------------------------------------------------------------------
/scripts/class-docker-cicd/clean-jenkins-data.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BASE="${HOME}/class-docker-cicd"
4 |
5 | echo "This will reset all the Jenkins data under ${BASE} !!!"
6 | echo
7 | echo "Are you sure this is what you want to do?"
8 | read -p "You must type 'yes' to confirm: " -r
9 | echo
10 | if [[ $REPLY == "yes" ]]; then
11 | rm -rf ${BASE}/layout/jenkins/data/*
12 | rm -rf ${BASE}/layout/jenkins/data/.groovy
13 | rm -rf ${BASE}/layout/jenkins/data/.java
14 | echo "completed"
15 | else
16 | echo "aborted"
17 | fi
18 |
19 |
--------------------------------------------------------------------------------
/terraform/bin/setup_managers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -u
5 |
6 | source ./bin/ip_vars.sh 1> /dev/null
7 |
8 | for i in "${secondary_manager_ips[@]}"
9 | do
10 | ssh -o "IdentitiesOnly=yes" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o "BatchMode=yes" -i ~/.ssh/oreilly_aws ubuntu@${i} "sudo docker swarm join --token ${SWARM_MANAGER_TOKEN} ${primary_manager_ip}:2377"
11 | done
12 |
13 | echo
14 | echo "Test your setup with:"
15 | echo
16 | echo "docker -H ${primary_manager_ip}:2375 node list"
17 | echo
18 |
--------------------------------------------------------------------------------
/outyet/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.22.0 AS builder
2 | # Build Image
3 |
4 | COPY . /go/src/outyet
5 | WORKDIR /go/src/outyet
6 |
7 | ENV CGO_ENABLED=0
8 | ENV GOOS=linux
9 |
10 | RUN go get -v -d && \
11 | go install -v && \
12 | go test -v && \
13 | go build -ldflags "-s" -a -installsuffix cgo -o outyet .
14 |
15 | FROM alpine:latest AS deploy
16 | # Deploy Image
17 |
18 | RUN apk --no-cache add ca-certificates
19 |
20 | WORKDIR /
21 | COPY --from=builder /go/src/outyet/outyet .
22 | # (or) COPY --from=0 /go/src/outyet/outyet .
23 |
24 | EXPOSE 8080
25 |
26 | CMD ["/outyet", "-version", "1.22.0", "-poll", "600s", "-http", ":8080"]
27 |
--------------------------------------------------------------------------------
/scripts/docker-workshop/clean-jenkins-data.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env powershell
2 |
3 | $BASE = "$HOME\docker-workshop"
4 |
5 | Write-Host "This will reset all the Jenkins data under $BASE !!!"
6 | Write-Host ""
7 | Write-Host "Are you sure this is what you want to do?"
8 |
9 | $confirmation = Read-Host "You must type 'yes' to confirm: "
10 | if ($confirmation -eq 'yes') {
11 | rm "$BASE/layout/jenkins/data/*" -r -fo
12 | rm "$BASE/layout/jenkins/data/.groovy" -r -fo
13 | rm "$BASE/layout/jenkins/data/.java" -r -fo
14 | cp "$BASE/layout/postgres/data/.git_keep" "$BASE/layout/jenkins/data/.git_keep"
15 | Write-Host "completed"
16 | } else {
17 | Write-Host "aborted"
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/scripts/class-docker-cicd/clean-jenkins-data.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env powershell
2 |
3 | $BASE = "$HOME\class-docker-cicd"
4 |
5 | Write-Host "This will reset all the Jenkins data under $BASE !!!"
6 | Write-Host ""
7 | Write-Host "Are you sure this is what you want to do?"
8 |
9 | $confirmation = Read-Host "You must type 'yes' to confirm: "
10 | if ($confirmation -eq 'yes') {
11 | rm "$BASE/layout/jenkins/data/*" -r -fo
12 | rm "$BASE/layout/jenkins/data/.groovy" -r -fo
13 | rm "$BASE/layout/jenkins/data/.java" -r -fo
14 | cp "$BASE/layout/postgres/data/.git_keep" "$BASE/layout/jenkins/data/.git_keep"
15 | Write-Host "completed"
16 | } else {
17 | Write-Host "aborted"
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/scripts/docker-workshop/clean-all-data.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BASE="${HOME}/docker-workshop"
4 |
5 | echo "This will reset all the class data under ${BASE} !!!"
6 | echo
7 | echo "Are you sure this is what you want to do?"
8 | read -p "You must type 'yes' to confirm: " -r
9 | echo
10 | if [[ $REPLY == "yes" ]]; then
11 | rm -rf ${BASE}/layout/postgres/data/data
12 | rm -rf ${BASE}/layout/registry/data/docker
13 | rm -rf ${BASE}/layout/jenkins/data/*
14 | rm -rf ${BASE}/layout/jenkins/data/.groovy
15 | rm -rf ${BASE}/layout/jenkins/data/.java
16 | rm -rf ${BASE}/layout/gogs/data/git
17 | rm -rf ${BASE}/layout/gogs/data/gogs
18 | rm -rf ${BASE}/layout/gogs/data/ssh
19 | echo "completed"
20 | else
21 | echo "aborted"
22 | fi
23 |
24 |
--------------------------------------------------------------------------------
/scripts/class-docker-cicd/clean-all-data.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BASE="${HOME}/class-docker-cicd"
4 |
5 | echo "This will reset all the class data under ${BASE} !!!"
6 | echo
7 | echo "Are you sure this is what you want to do?"
8 | read -p "You must type 'yes' to confirm: " -r
9 | echo
10 | if [[ $REPLY == "yes" ]]; then
11 | rm -rf ${BASE}/layout/postgres/data/data
12 | rm -rf ${BASE}/layout/registry/data/docker
13 | rm -rf ${BASE}/layout/jenkins/data/*
14 | rm -rf ${BASE}/layout/jenkins/data/.groovy
15 | rm -rf ${BASE}/layout/jenkins/data/.java
16 | rm -rf ${BASE}/layout/gogs/data/git
17 | rm -rf ${BASE}/layout/gogs/data/gogs
18 | rm -rf ${BASE}/layout/gogs/data/ssh
19 | echo "completed"
20 | else
21 | echo "aborted"
22 | fi
23 |
24 |
--------------------------------------------------------------------------------
/outyet/Dockerfile.minimal:
--------------------------------------------------------------------------------
1 | FROM golang:1.22.0 AS builder
2 | # Build Image
3 |
4 | COPY . /go/src/outyet
5 | WORKDIR /go/src/outyet
6 |
7 | ENV CGO_ENABLED=0
8 | ENV GOOS=linux
9 |
10 | RUN go get -v -d && \
11 | go install -v && \
12 | go test -v && \
13 | go build -ldflags "-s" -a -installsuffix cgo -o outyet .
14 |
15 | FROM scratch AS deploy
16 | # Deploy Image
17 |
18 | WORKDIR /
19 | COPY --from=builder /go/src/outyet/outyet .
20 | COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
21 | # (or) COPY --from=0 /go/src/outyet/outyet .
22 | # (or) COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
23 |
24 | EXPOSE 8080
25 |
26 | CMD ["/outyet", "-version", "1.22.0", "-poll", "600s", "-http", ":8080"]
27 |
--------------------------------------------------------------------------------
/terraform/bin/self_healing.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -u
5 |
6 | source ./bin/ip_vars.sh 1> /dev/null
7 |
8 | curl -s -o /dev/null -w "%{http_code}" http://${primary_manager_ip}:80/
9 | echo; echo
10 | docker -H ${primary_manager_ip}:2375 service ls --format "{{.ID}}: {{.Name}} {{.Replicas}}"
11 | echo
12 | set +e
13 | curl -s -o /dev/null -w "%{http_code}" http://${primary_manager_ip}:80/die
14 | set -e
15 | echo; echo
16 | docker -H ${primary_manager_ip}:2375 service ls --format "{{.ID}}: {{.Name}} {{.Replicas}}"
17 | echo
18 | for i in {1..4}; do
19 | sleep 1
20 | curl -s -o /dev/null -w "%{http_code}" http://${primary_manager_ip}:80/
21 | echo; echo
22 | docker -H ${primary_manager_ip}:2375 service ls --format "{{.ID}}: {{.Name}} {{.Replicas}}"
23 | echo
24 | done
25 |
26 |
--------------------------------------------------------------------------------
/registry/config.yaml:
--------------------------------------------------------------------------------
1 | version: 0.1
2 | log:
3 | accesslog:
4 | disabled: false
5 | level: info
6 | fields:
7 | service: registry
8 | environment: development
9 | storage:
10 | delete:
11 | enabled: true
12 | cache:
13 | blobdescriptor: inmemory
14 | filesystem:
15 | rootdirectory: /var/lib/registry
16 | http:
17 | addr: :5000
18 | headers:
19 | X-Content-Type-Options: [nosniff]
20 | auth:
21 | htpasswd:
22 | realm: class-realm
23 | path: /htpasswd
24 | notifications:
25 | endpoints:
26 | - name: local-8083
27 | url: http://localhost:8083/callback
28 | timeout: 1s
29 | threshold: 10
30 | backoff: 1s
31 | disabled: true
32 | health:
33 | storagedriver:
34 | enabled: true
35 | interval: 10s
36 | threshold: 3
37 |
--------------------------------------------------------------------------------
/terraform/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_profile" {
2 | description = "AWS Profile for credentials"
3 | default = "oreilly-aws"
4 | }
5 |
6 | variable "ssh_private_key_path" {
7 | description = "Path to EC2 SSH private key"
8 | default = "/Users/spkane/.ssh/oreilly_aws"
9 | }
10 |
11 | variable "ssh_public_key_path" {
12 | description = "Path to EC2 SSH public key"
13 | default = "/Users/spkane/.ssh/oreilly_aws.pub"
14 | }
15 |
16 | #variable "public_ip_path" {
17 | # description = "Path to file containing public IP"
18 | # default = "/Users/spkane/.public_home_ip"
19 | #}
20 |
21 | variable "swarm_manager_count" {
22 | description = "Number of swarm managers"
23 | default = 3
24 | }
25 |
26 | variable "swarm_worker_count" {
27 | description = "Number of swarm workers"
28 | default = 4
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/registry/certs/san.cnf:
--------------------------------------------------------------------------------
1 | [ req ]
2 | default_bits = 2048
3 | distinguished_name = req_distinguished_name
4 | req_extensions = v3_req
5 |
6 | [req_distinguished_name]
7 | countryName = Country Name (2 letter code)
8 | countryName_default = US
9 | stateOrProvinceName = State or Province Name (full name)
10 | stateOrProvinceName_default = OR
11 | localityName = Locality Name (eg, city)
12 | localityName_default = Portland
13 | organizationalUnitName = Organizational Unit Name (eg, section)
14 | organizationalUnitName_default = example
15 | commonName = example.org
16 | commonName_max = 64
17 |
18 | [ v3_req ]
19 | # Extensions to add to a certificate request
20 | basicConstraints = CA:FALSE
21 | subjectAltName = @alt_names
22 |
23 | [alt_names]
24 | DNS.1 = private-registry.localdomain
25 | DNS.2 = localhost.localdomain
26 | DNS.3 = localhost
27 | IP.1 = 127.0.0.1
28 |
--------------------------------------------------------------------------------
/scripts/docker-workshop/clean-all-data.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env powershell
2 |
3 | $BASE = "$HOME\docker-workshop"
4 |
5 | Write-Host "This will reset all the class data under $BASE !!!"
6 | Write-Host ""
7 | Write-Host "Are you sure this is what you want to do?"
8 |
9 | $confirmation = Read-Host "You must type 'yes' to confirm: "
10 | if ($confirmation -eq 'yes') {
11 | rm "$BASE/layout/postgres/data/data" -r -fo
12 | rm "$BASE/layout/registry/data/docker" -r -fo
13 | rm "$BASE/layout/jenkins/data/*" -r -fo
14 | rm "$BASE/layout/jenkins/data/.groovy" -r -fo
15 | rm "$BASE/layout/jenkins/data/.java" -r -fo
16 | rm "$BASE/layout/gogs/data/git" -r -fo
17 | rm "$BASE/layout/gogs/data/gogs" -r -fo
18 | rm "$BASE/layout/gogs/data/ssh" -r -fo
19 | cp "$BASE/layout/postgres/data/.git_keep" "$BASE/layout/jenkins/data/.git_keep"
20 | Write-Host "completed"
21 | } else {
22 | Write-Host "aborted"
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/scripts/class-docker-cicd/clean-all-data.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env powershell
2 |
3 | $BASE = "$HOME\class-docker-cicd"
4 |
5 | Write-Host "This will reset all the class data under $BASE !!!"
6 | Write-Host ""
7 | Write-Host "Are you sure this is what you want to do?"
8 |
9 | $confirmation = Read-Host "You must type 'yes' to confirm: "
10 | if ($confirmation -eq 'yes') {
11 | rm "$BASE/layout/postgres/data/data" -r -fo
12 | rm "$BASE/layout/registry/data/docker" -r -fo
13 | rm "$BASE/layout/jenkins/data/*" -r -fo
14 | rm "$BASE/layout/jenkins/data/.groovy" -r -fo
15 | rm "$BASE/layout/jenkins/data/.java" -r -fo
16 | rm "$BASE/layout/gogs/data/git" -r -fo
17 | rm "$BASE/layout/gogs/data/gogs" -r -fo
18 | rm "$BASE/layout/gogs/data/ssh" -r -fo
19 | cp "$BASE/layout/postgres/data/.git_keep" "$BASE/layout/jenkins/data/.git_keep"
20 | Write-Host "completed"
21 | } else {
22 | Write-Host "aborted"
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/terraform/bin/ip_vars.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
4 | echo "The script ${BASH_SOURCE[0]} is being sourced..."
5 | echo
6 | else
7 | echo "You must source this bash script, not run it directly."
8 | echo
9 | exit 1
10 | fi
11 |
12 | export managers=$(terraform output | grep manager | cut -d " " -f 3)
13 | export workers=$(terraform output | grep worker | cut -d " " -f 3)
14 | num=0
15 | for i in $(echo $managers | sed "s/,/ /g" | sed 's/"/ /g' )
16 | do
17 | all_manager_ips[${num}]=${i}
18 | echo "\${all_manager_ips[${num}]}: ${all_manager_ips[${num}]}"
19 | let num+=1
20 | done
21 | export primary_manager_ip=(${all_manager_ips[0]})
22 | export secondary_manager_ips=(${all_manager_ips[@]:1})
23 | export worker_ips=()
24 | num=0
25 | for i in $(echo $workers | sed "s/,/ /g" | sed 's/"/ /g' )
26 | do
27 | worker_ips[${num}]=${i}
28 | echo "\${worker_ips[${num}]}: ${worker_ips[${num}]}"
29 | let num+=1
30 | done
31 |
32 |
--------------------------------------------------------------------------------
/registry/certs/domain.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC+jCCAeICCQCHPFP6qP40xzANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGEwJV
3 | UzELMAkGA1UECAwCT1IxETAPBgNVBAcMCFBvcnRsYW5kMRAwDgYDVQQLDAdleGFt
4 | cGxlMB4XDTIwMDExMjE3NDgzOFoXDTMwMDEwOTE3NDgzOFowPzELMAkGA1UEBhMC
5 | VVMxCzAJBgNVBAgMAk9SMREwDwYDVQQHDAhQb3J0bGFuZDEQMA4GA1UECwwHZXhh
6 | bXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKch+w4MDM46fpz
7 | BwUGysJA5xSKznjfr+9nSTLZ48k3kVXvwJ+1yYxJwa/yt8937ZTlQnQSjxphSu7l
8 | Br80VnjEAvO5Eq+xY7IfubPiSRHtTmExvRdRAmhEN00EF+Ib5cz5fcgiy1LSAfs4
9 | mo+jSc0N0+Y6mKm/08VjCraJs1XfchkmQlLItyeR14CA4x/Jevol/DiNCCH9Mi1y
10 | YK3VyY8gHeW0HE2VvhFj7D+H/L+OzNeh63GMzrYVOm60Q7aPlTtcL0nwAOMZcaVg
11 | FvnEWmR5uPHffDqZkW7z6xxc2O2q05xC4ZAOg5Q8g3bh7QmbGvMlSvJlBfk/9VD8
12 | I9NCijUCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeQiO0S3c5BphvjR43wP5dxy8
13 | qoPHZFAioHAiwipwHj1VapS4O1hKdj7WAnV0gJ/VfyMZzChe35V4Q83sRGNil6dA
14 | 2OTX4ql7V5TNE5txvb48n09txWTFk5th1Uvw9JvrW7gqBpmy1rJ/3iSFU5+kX8TD
15 | wtX1hZp81gtkTW0MijVSwkcy+cRMtsXPUy69DbO1A7Ik3W34KLMnA0uJ01rytrI4
16 | kn4z4BL+YaNJpBOIb44CpsrXxh4rRF0lyYggtrvKQrdNFacM4aM7uGaqNXH50pFq
17 | +UNf1IWcr+4qvqFGblnEwRVTyedfL3d0mM2gia3YVUQK/JrH3GsRrcX5kKziUQ==
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/gogs/conf/app.ini:
--------------------------------------------------------------------------------
1 | BRAND_NAME = Gogs
2 | RUN_USER = git
3 | RUN_MODE = prod
4 |
5 | [repository]
6 | DEFAULT_BRANCH = main
7 | ROOT = /data/git/gogs-repositories
8 |
9 | [security]
10 | LOCAL_NETWORK_ALLOWLIST = jenkins
11 | INSTALL_LOCK = true
12 | SECRET_KEY = 1HianFdxykORQym
13 |
14 | [database]
15 | TYPE = postgres
16 | HOST = postgres:5432
17 | NAME = gogs
18 | SCHEMA = public
19 | USER = postgres
20 | PASSWORD = myuser-pw!
21 | SSL_MODE = disable
22 | PATH = /app/gogs/data/gogs.db
23 |
24 | [server]
25 | DOMAIN = localhost
26 | HTTP_PORT = 3000
27 | EXTERNAL_URL = http://127.0.0.1:10090/
28 | DISABLE_SSH = false
29 | SSH_PORT = 10022
30 | START_SSH_SERVER = false
31 | OFFLINE_MODE = false
32 |
33 | [mailer]
34 | ENABLED = false
35 |
36 | [auth]
37 | REQUIRE_EMAIL_CONFIRMATION = false
38 | DISABLE_REGISTRATION = false
39 | ENABLE_REGISTRATION_CAPTCHA = true
40 | REQUIRE_SIGNIN_VIEW = false
41 |
42 | [user]
43 | ENABLE_EMAIL_NOTIFICATION = false
44 |
45 | [picture]
46 | DISABLE_GRAVATAR = false
47 | ENABLE_FEDERATED_AVATAR = false
48 |
49 | [session]
50 | PROVIDER = file
51 |
52 | [log]
53 | MODE = file
54 | LEVEL = Info
55 | ROOT_PATH = /app/gogs/log
56 |
--------------------------------------------------------------------------------
/terraform/security-group.tf:
--------------------------------------------------------------------------------
1 | /* Default security group */
2 | resource "aws_security_group" "swarm" {
3 | name = "swarm-training-spkane"
4 | description = "Default security group that allows inbound and outbound traffic from all instances in the VPC"
5 | vpc_id = data.aws_vpc.default.id
6 |
7 | ingress {
8 | from_port = "0"
9 | to_port = "0"
10 | protocol = "-1"
11 | cidr_blocks = ["0.0.0.0/0"]
12 | self = true
13 | }
14 |
15 | ingress {
16 | from_port = 22
17 | to_port = 22
18 | protocol = "tcp"
19 | cidr_blocks = ["0.0.0.0/0"]
20 | }
21 |
22 | ingress {
23 | from_port = 80
24 | to_port = 80
25 | protocol = "tcp"
26 | cidr_blocks = ["${data.external.public_ip.result.public_ip}/32"]
27 | }
28 |
29 | ingress {
30 | from_port = 8080
31 | to_port = 8080
32 | protocol = "tcp"
33 | cidr_blocks = ["${data.external.public_ip.result.public_ip}/32"]
34 | }
35 |
36 | ingress {
37 | from_port = 2375
38 | to_port = 2375
39 | protocol = "tcp"
40 | cidr_blocks = ["${data.external.public_ip.result.public_ip}/32"]
41 | }
42 |
43 | egress {
44 | from_port = "0"
45 | to_port = "0"
46 | protocol = "-1"
47 | cidr_blocks = ["0.0.0.0/0"]
48 | self = true
49 | }
50 | egress {
51 | from_port = 22
52 | to_port = 22
53 | protocol = "tcp"
54 | cidr_blocks = ["0.0.0.0/0"]
55 | }
56 |
57 | tags = {
58 | Name = "swarm-training-spkane"
59 | Trainer = "Sean P. Kane"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/registry/certs/domain.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCynIfsODAzOOn6
3 | cwcFBsrCQOcUis5436/vZ0ky2ePJN5FV78CftcmMScGv8rfPd+2U5UJ0Eo8aYUru
4 | 5Qa/NFZ4xALzuRKvsWOyH7mz4kkR7U5hMb0XUQJoRDdNBBfiG+XM+X3IIstS0gH7
5 | OJqPo0nNDdPmOpipv9PFYwq2ibNV33IZJkJSyLcnkdeAgOMfyXr6Jfw4jQgh/TIt
6 | cmCt1cmPIB3ltBxNlb4RY+w/h/y/jszXoetxjM62FTputEO2j5U7XC9J8ADjGXGl
7 | YBb5xFpkebjx33w6mZFu8+scXNjtqtOcQuGQDoOUPIN24e0JmxrzJUryZQX5P/VQ
8 | /CPTQoo1AgMBAAECggEBALChT2Fw52mgPPKp0iVMZDLZ0CtmYWzzeJ79u0uIYlTY
9 | mOctI4ZNVbVgMyR2mQOYi+CVH7R9rfregCXjY1quvVzMKkcvnKUWfYrnCNQ1USFj
10 | VgGUGHT4bbMC0tVc2OmHwSeFCrhigEO03rS7c03cot0fcY/aHqKvyxMGMM/3ONwP
11 | ZrmvqtH41+n66kELvLEjhB+th55bF8DPzCVUj3aDFQ+GbwECT0jsLYFsqALy8zes
12 | 6lztwnvVVDfTZDukPaz6EGgkz30PSA8sos/nHDPdVUitcfCjCMqb3EaUxyswypBW
13 | rBanKhZTV6uKgoZZnQM3xcYHiyY4PJy2zMHpeFdI+zkCgYEA4o37Mham4BEzTmvC
14 | esHSbXBctqn6U5rXNHb1/KY56HnYAGRU0CaXHRWRlpc/wfAEfGZm3mD0DtF/AM4a
15 | j7WvfpqNVTMp1u6a1DZpqNwY07lQojHetvh3TqUeaHieZ8CSioEb8q4cRZkWZXIo
16 | R5DZDCH1+b0Te1KlqoLj2rMZfpsCgYEAydNdaoaNOb1RKOoPXjpVzPl+affy1Qdq
17 | Mi4nDThZj28fZ4XWplWDFjKhnApHLamgqcjBI+vSpgodCeQw6YFiy+y+/XlArEOW
18 | OGPfDbdPtSDoSFiSeQhRpkuWbf878VVpYqxVZ+/B+x6mnl/gAOMtEUxrfKrNVOEo
19 | 8eM39rWtv28CgYAaf0Ke5BlWYYyfomjXlK240Qh28MBvYM/EuhkhGIvzTbTert1g
20 | jvLjmu8xLrVtSFYt+ogTgEFrLkNtY62lmzlQVGEtUtOU6MlBArAu6LcapDTzE2Qa
21 | AEtr7lH1JA5a0iIRgvIy2vxBg5sj+EsPu7g2/A3ZzKxnow3vOGnP3Vyg+wKBgHHa
22 | zgkpLIRVG3LUT6UdjYebe8f1+0RX8X2rcZZQop1616GD7CpbdR7Roz+uwKau2ZbO
23 | TL6h62yFqgoJc9pWhlB6FuhRPb2wRw86r/tB3TJWBRPC+6ZRnhYM8CjPYpZrU485
24 | ntiKdcjfaqlPdsOpZKQskzp59Gmct4d1Yf3IUeL7AoGBAL1WZ3kwRK+/YoWmbGJN
25 | FDftUroAbUbVP0pf2sKFKlG7WsO4veIKcIbGO9yGmQwUGxo9T4nSsJULDNkVRcO0
26 | Zg2AetO9AsHTrjF0Zbvxa3EJrQNZbPEOGP4Mxf6aYDyFw5ewTnzhbqECdbw/QYBk
27 | OBhH9OI8/3vz4neaspBQrA1p
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/compose/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | postgres:
3 | container_name: class_postgres_4
4 | image: docker.io/postgres:15
5 | restart: unless-stopped
6 | networks:
7 | - my-net
8 | ports:
9 | - "15432:5432"
10 | environment:
11 | POSTGRES_USER: "postgres"
12 | POSTGRES_PASSWORD: "${MY_PG_PASS}"
13 | POSTGRES_DB: "gogs"
14 | healthcheck:
15 | test: ["CMD", "pg_isready", "-U", "postgres", "-d", "gogs"]
16 | interval: 10s
17 | timeout: 5s
18 | retries: 5
19 | gogs:
20 | container_name: class_gogs_4
21 | image: docker.io/gogs/gogs:0.13
22 | restart: unless-stopped
23 | networks:
24 | - my-net
25 | depends_on:
26 | # https://docs.docker.com/compose/compose-file/compose-file-v2/#depends_on
27 | # https://docs.docker.com/compose/compose-file/compose-file-v2/#healthcheck
28 | postgres:
29 | condition: service_healthy
30 | ports:
31 | - "10022:22"
32 | - "10090:3000"
33 | volumes:
34 | - "../gogs/conf:/data/gogs/conf"
35 | registry:
36 | container_name: class_registry_4
37 | image: docker.io/registry:2.8.2
38 | restart: unless-stopped
39 | networks:
40 | - my-net
41 | ports:
42 | - "5000:5000"
43 | environment:
44 | REGISTRY_HTTP_TLS_CERTIFICATE: "/certs/domain.crt"
45 | REGISTRY_HTTP_TLS_KEY: "/certs/domain.key"
46 | REGISTRY_HTTP_SECRET: "iuehfio73bt8dobq"
47 | volumes:
48 | - "../registry/config.yaml:/etc/docker/registry/config.yaml"
49 | - "../registry/htpasswd:/htpasswd"
50 | - "../registry/data:/var/lib/registry"
51 | - "../registry/certs:/certs"
52 | jenkins:
53 | container_name: class_jenkins_4
54 | #build:
55 | # context: ../../jenkins/docker
56 | # If you can't build, use this image: `spkane/dc-201-jenkins:latest`
57 | image: docker.io/spkane/dc-201-jenkins:latest
58 | restart: unless-stopped
59 | networks:
60 | - my-net
61 | ports:
62 | - "10091:8080"
63 | - "50000:50000"
64 | volumes:
65 | - "../jenkins/data:/var/jenkins_home"
66 | - "/var/run/docker.sock:/var/run/docker.sock"
67 | networks:
68 | my-net:
69 | driver: bridge
70 |
--------------------------------------------------------------------------------
/jenkins/jobs/outyet/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
Hostname: {{.Hostname}}
220 |{{.ConfigMessage}}
222 | {{.SecretMessage}}