mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-23 12:30:41 +01:00
new dockerfiles, circleci v2
This commit is contained in:
parent
8bb45c2970
commit
ccc017cbed
91
.circleci/config.yml
Normal file
91
.circleci/config.yml
Normal file
@ -0,0 +1,91 @@
|
||||
# This configuration was automatically generated from a CircleCI 1.0 config.
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
machine: true
|
||||
# we hard code this because even in a fork our code references the canonical import urls
|
||||
working_directory: ~/.go_workspace/src/github.com/ansible-semaphore/semaphore
|
||||
steps:
|
||||
# Remove go and restore the dependency cache
|
||||
- run: sudo rm -rf /usr/local/go
|
||||
- run: mkdir -p ${GOPATH}/bin
|
||||
- restore_cache:
|
||||
keys:
|
||||
# This branch if available
|
||||
- v3-dep-{{ .Branch }}-
|
||||
# Default branch if not
|
||||
- v3-dep-develop-
|
||||
# Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
|
||||
- v3-dep-
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install rpm
|
||||
# Install node and go
|
||||
- run:
|
||||
name: Install node
|
||||
command: |
|
||||
set +e
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.5/install.sh | bash
|
||||
export NVM_DIR="/opt/circleci/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
nvm install 8.2.0 && nvm alias default 8.2.0
|
||||
# Each step uses the same `$BASH_ENV`, so need to modify it
|
||||
echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
|
||||
echo "[ -s \"$NVM_DIR/nvm.sh\" ] && . \"$NVM_DIR/nvm.sh\"" >> $BASH_ENV
|
||||
- run: sudo curl -L https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz > /tmp/go.tar.gz
|
||||
- run: sudo tar -C /usr/local -xzf /tmp/go.tar.gz
|
||||
# Needed for task orchestration
|
||||
- run: go get -u -v github.com/go-task/task/cmd/task
|
||||
# Needed only in ci to post coverage reports
|
||||
- run: go get github.com/schrej/godacov
|
||||
# Get app and install all its deps
|
||||
- checkout
|
||||
- run: task deps
|
||||
- run: task deps:docker
|
||||
# Save dependency cache
|
||||
- save_cache:
|
||||
key: v3-dep-{{ .Branch }}-{{ epoch }}
|
||||
paths:
|
||||
- ~/.go_workspace/src/github.com/ansible-semaphore/semaphore
|
||||
- ~/.go_workspace/bin
|
||||
- /opt/circleci/.nvm
|
||||
# Post cache compile
|
||||
- run: task compile
|
||||
# Test
|
||||
# This looks like utter filth in circleci v2 but we have no choice apart from this escaping madness
|
||||
- run: "cat > config.json <<EOF\n{\n\t\"mysql\": {\n\t\t\"host\": \"0.0.0.0:3306\"\
|
||||
,\n\t\t\"user\": \"root\",\n\t\t\"pass\": \"\",\n\t\t\"name\": \"circle_test\"\
|
||||
\n\t},\n\t\"email_alert\": false\n}\nEOF\n"
|
||||
- run: |
|
||||
docker run -d -p "3306:3306" --health-cmd='mysqladmin ping --silent' -e MYSQL_ALLOW_EMPTY_PASSWORD=true -e MYSQL_DATABASE=circle_test --name=mysql mysql:5.6
|
||||
function getContainerHealth {
|
||||
docker inspect --format "{{json .State.Health.Status }}" $1
|
||||
}
|
||||
|
||||
function waitContainer {
|
||||
while STATUS=$(getContainerHealth $1); [ $STATUS != "\"healthy\"" ]; do
|
||||
if [ $STATUS == "\"unhealthy\"" ]; then
|
||||
exit -1
|
||||
fi
|
||||
printf .
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
waitContainer mysql
|
||||
- run: go run cli/main.go --migrate -config config.json
|
||||
- run: docker stop mysql && docker rm mysql
|
||||
- run: task test
|
||||
- run: context=prod task docker:test
|
||||
# Build artifacts for all architectures
|
||||
- run: task build
|
||||
# Post coverage
|
||||
- run: godacov -t "${CODACY_TOKEN}" -r ./coverage.out -c "${CIRCLE_SHA1}" || true
|
||||
# Teardown
|
||||
# Save test results
|
||||
- store_test_results:
|
||||
path: ~/.go_workspace/src/github.com/ansible-semaphore/semaphore/coverage.out
|
||||
# Save artifacts
|
||||
- store_artifacts:
|
||||
path: ~/.go_workspace/src/github.com/ansible-semaphore/semaphore/bin
|
||||
- store_artifacts:
|
||||
path: ~/.go_workspace/src/github.com/ansible-semaphore/semaphore/coverage.out
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,8 +9,6 @@ config.json
|
||||
node_modules/
|
||||
|
||||
.idea/
|
||||
caddyfile
|
||||
cli/semaphore_*
|
||||
bin/
|
||||
*-packr.go
|
||||
util/version.go
|
||||
|
16
Dockerfile
16
Dockerfile
@ -1,16 +0,0 @@
|
||||
FROM alpine:3.5
|
||||
|
||||
ENV SEMAPHORE_VERSION="2.3.0" SEMAPHORE_ARCH="linux_amd64"
|
||||
|
||||
RUN apk add --no-cache git ansible mysql-client curl openssh-client tini && \
|
||||
curl -sSfL "https://github.com/ansible-semaphore/semaphore/releases/download/v$SEMAPHORE_VERSION/semaphore_$SEMAPHORE_ARCH" > /usr/bin/semaphore && \
|
||||
chmod +x /usr/bin/semaphore && mkdir -p /etc/semaphore/playbooks
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ADD ./scripts/docker-startup.sh /usr/bin/semaphore-startup.sh
|
||||
RUN chmod +x /usr/bin/semaphore-startup.sh
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
|
||||
CMD ["/usr/bin/semaphore-startup.sh", "/usr/bin/semaphore", "-config", "/etc/semaphore/semaphore_config.json"]
|
120
Taskfile.yml
120
Taskfile.yml
@ -143,3 +143,123 @@ tasks:
|
||||
ci:artifacts:
|
||||
cmds:
|
||||
- rsync -a bin/ $CIRCLE_ARTIFACTS/
|
||||
|
||||
# docker(-compose) commands
|
||||
dc:dev:
|
||||
desc: build and start a development stack using docker-compose
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: dev
|
||||
args: build semaphore_dev
|
||||
compose: true
|
||||
- task: dc:up
|
||||
vars:
|
||||
context: dev
|
||||
|
||||
# convenience function to build and start a production like stack
|
||||
dc:prod:
|
||||
desc: build and start a production like stack using docker-compose
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: prod
|
||||
args: build semaphore
|
||||
compose: true
|
||||
- task: dc:up
|
||||
vars:
|
||||
context: prod
|
||||
|
||||
dc:up:
|
||||
desc: start a docker-compose instance, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: up --abort-on-container-exit
|
||||
context: "{{ .context }}"
|
||||
|
||||
dc:build:
|
||||
desc: build a set of docker-compose containers, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: build
|
||||
context: "{{ .context }}"
|
||||
|
||||
dc:down:
|
||||
desc: down a docker-compose instance, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: down
|
||||
context: "{{ .context }}"
|
||||
|
||||
dc:stop:
|
||||
desc: stop a docker-compose instance, requires context
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
compose: true
|
||||
args: stop
|
||||
context: "{{ .context }}"
|
||||
|
||||
docker:build:
|
||||
desc: Build an image for Semaphore, requires context
|
||||
vars:
|
||||
tag: "{{ if .tag }}{{ .tag }}{{ else }}latest{{ end }}"
|
||||
cmds:
|
||||
- task: docker
|
||||
vars:
|
||||
context: "{{ .context }}"
|
||||
action: build
|
||||
tag: "{{ .tag }}"
|
||||
args: -t castawaylabs/semaphore:{{ .tag }} .
|
||||
|
||||
deps:docker:
|
||||
desc: Install docker testing dependencies. These must be installed explicitly and are not included in the general deps task.
|
||||
status:
|
||||
- test -f /usr/local/bin/goss
|
||||
- test -f /usr/local/bin/dgoss
|
||||
- test -f /usr/local/bin/hadolint
|
||||
cmds:
|
||||
- sudo curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.5/goss-linux-amd64 -o /usr/local/bin/goss
|
||||
- sudo chmod +rx /usr/local/bin/goss
|
||||
- sudo curl -L https://raw.githubusercontent.com/aelsabbahy/goss/v0.3.5/extras/dgoss/dgoss -o /usr/local/bin/dgoss
|
||||
- sudo chmod +rx /usr/local/bin/dgoss
|
||||
- sudo curl -L https://github.com/hadolint/hadolint/releases/download/v1.5.0/hadolint-Linux-x86_64 -o /usr/local/bin/hadolint
|
||||
- sudo chmod +rx /usr/local/bin/hadolint
|
||||
|
||||
docker:test:
|
||||
desc: Test docker containers by building them, running tests and deleting
|
||||
deps: ['deps:docker']
|
||||
cmds:
|
||||
- task: docker:lint
|
||||
vars:
|
||||
context: "{{ .context }}"
|
||||
- task: docker:build
|
||||
vars:
|
||||
tag: "{{ .context }}-test"
|
||||
- task: docker:goss
|
||||
- docker rmi "castawaylabs/semaphore:{{ .context }}-test"
|
||||
|
||||
docker:goss:
|
||||
dir: "deployment/docker/{{ .context}}"
|
||||
deps: ['deps:docker']
|
||||
cmds:
|
||||
- GOSS_FILES_STRATEGY='cp' dgoss run -it "castawaylabs/semaphore:{{ .context }}-test"
|
||||
|
||||
docker:lint:
|
||||
desc: hadolint a dockerfile. Ignores version pinning warning
|
||||
dir: "deployment/docker/{{ .context}}"
|
||||
cmds:
|
||||
- hadolint Dockerfile --ignore DL3018
|
||||
|
||||
# templated command to reduce code duplication
|
||||
docker:
|
||||
vars:
|
||||
docker_root: deployment/docker/
|
||||
cmds:
|
||||
- docker{{ if .compose }}-compose{{ end }} {{ if .action }}{{ .action }}{{ end }} -f {{ .docker_root }}{{ .context }}/{{ if .compose }}docker-compose.yml{{ else }}Dockerfile{{ end }} {{if .args }}{{ .args }}{{ end }}
|
||||
|
53
circle.yml
53
circle.yml
@ -1,53 +0,0 @@
|
||||
machine:
|
||||
environment:
|
||||
CPATH: "${HOME}/.go_workspace/src/github.com/ansible-semaphore"
|
||||
node:
|
||||
version: 8.2.0
|
||||
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- sudo apt-get install rpm
|
||||
- mkdir -p ${GOPATH}/bin
|
||||
- rm -rf ${CPATH} && mkdir -p ${CPATH}
|
||||
- ln -sfn ${HOME}/${CIRCLE_PROJECT_REPONAME} ${CPATH}
|
||||
- sudo rm -rf /usr/local/go
|
||||
- sudo curl -L https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz > /tmp/go.tar.gz
|
||||
- sudo tar -C /usr/local -xzf /tmp/go.tar.gz
|
||||
- go get -u -v github.com/go-task/task/cmd/task
|
||||
- go get github.com/schrej/godacov
|
||||
- cd ${CPATH}/${CIRCLE_PROJECT_REPONAME} && task deps
|
||||
override:
|
||||
- task compile
|
||||
|
||||
test:
|
||||
pre:
|
||||
- |
|
||||
cat > config.json <<EOF
|
||||
{
|
||||
"mysql": {
|
||||
"host": "127.0.0.1:3306",
|
||||
"user": "ubuntu",
|
||||
"pass": "",
|
||||
"name": "circle_test"
|
||||
},
|
||||
"session_db": "127.0.0.1:6379",
|
||||
"port": ":8010",
|
||||
"email_alert": false
|
||||
}
|
||||
EOF
|
||||
- go run cli/main.go --migrate -config config.json
|
||||
override:
|
||||
- cd ${CPATH}/${CIRCLE_PROJECT_REPONAME} && task test
|
||||
- task build
|
||||
- task ci:artifacts
|
||||
post:
|
||||
# We don't export the coverage secret to forks so we need this to always return successfully
|
||||
- godacov -t "${CODACY_TOKEN}" -r ./coverage.out -c "${CIRCLE_SHA1}" || true
|
||||
|
||||
deployment:
|
||||
tag:
|
||||
tag: /v[0-9]+(\.[0-9]+)*(-.*)*/
|
||||
owner: ansible-semaphore
|
||||
commands:
|
||||
- curl -sL https://git.io/goreleaser | bash
|
76
deployment/docker/Readme.md
Normal file
76
deployment/docker/Readme.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Docker Deployments
|
||||
|
||||
Production images for each tag, latest and the development branch will be pushed to [docker hub](https://hub.docker.com/r/castawaylabs/semaphore).
|
||||
To build images locally see the contexts included here and use the `d` and `dc` tasks in the root Taskfile.yml to help with building and running.
|
||||
|
||||
## Contexts
|
||||
|
||||
### Prod
|
||||
|
||||
To build a production image you should run
|
||||
|
||||
context=prod task docker:build
|
||||
|
||||
this will create an image called `castawaylabs/semaphore:latest` which will be compiled from the currently checked out code
|
||||
|
||||
This image is run as non root user 1001 (for PaaS systems such as openshift) and is build on alpine with added glibc.
|
||||
With ansible etc... installed in the container it is ~283MiB in size.
|
||||
|
||||
You will need to provide environmental variables so that the configuration can be built correctly for your environment.
|
||||
See `docker-compose.yml` for an example, or look at `../common/entrypoint` to see which variables are available
|
||||
|
||||
If you want to bulid an image with a custom tag you can optionally pass a tag to the command
|
||||
|
||||
context=prod tag=mybranch task docker:build
|
||||
|
||||
#### Example Configuration
|
||||
|
||||
To run Semaphore in a simple production-like docker configuration run the following command:
|
||||
|
||||
task dc:prod
|
||||
|
||||
You can then access Semaphore directly from the url http://localhost:8081/
|
||||
|
||||
#### SSL Termination Using Nginx
|
||||
|
||||
Generate a cert, ca cert, and key file and place into `prod/proxy/cert/` with
|
||||
these names:
|
||||
|
||||
* `cert.pem`
|
||||
* `privkey.pem`
|
||||
* `fullchain.pem`
|
||||
|
||||
(I've used letsencrypt generated certs with success.)
|
||||
|
||||
Run `task dc:prod` and your Semaphore instance will then be at the url
|
||||
https://localhost:8443
|
||||
|
||||
If you do not add certificates the container will create self-signed certs instead
|
||||
|
||||
## Dev
|
||||
|
||||
To start a development start you could run
|
||||
```
|
||||
context=dev task dc:up
|
||||
```
|
||||
The development stack will run `task watch` by default and `dc:up` will volume link the application in to the container.
|
||||
Without `dc:up` the application will run the version of the application which existed at image build time.
|
||||
|
||||
The development container is based on [micro-golang](https://github.com/twhiston/micro-golang)'s test base image
|
||||
which contains the go toolchain and glibc in alpine.
|
||||
|
||||
Because the test image links your local volume it expects that you have run `task deps` and `task compile` locally
|
||||
as necessary to make the application usable.
|
||||
|
||||
## Convenience Functions
|
||||
|
||||
### dc:dev
|
||||
|
||||
`dc:dev` rebuilds the development images and runs a development stack, with the semaphore root as a volume link
|
||||
This allows you to work inside the container with live code. The container has all the tools you need to build and test semaphore
|
||||
|
||||
### dc:prod
|
||||
|
||||
`dc:prod` rebuilds the production example images and starts the production-like stack.
|
||||
This will compile the application for the currently checked out code but will not leave build tools or source in the container.
|
||||
Therefore file changes will result in needing a rebuild.
|
@ -1,18 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
echoerr() { printf "%s\n" "$*" >&2; }
|
||||
|
||||
SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}"
|
||||
SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore}"
|
||||
|
||||
SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore_data}"
|
||||
# Semaphore database env config
|
||||
SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-127.0.0.1}"
|
||||
SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}"
|
||||
SEMAPHORE_DB_PORT="${SEMAPHORE_DB_PORT:-3306}"
|
||||
SEMAPHORE_DB="${SEMAPHORE_DB:-semaphore}"
|
||||
SEMAPHORE_DB_USER="${SEMAPHORE_DB_USER:-semaphore}"
|
||||
SEMAPHORE_DB_PASS="${SEMAPHORE_DB_PASS:-semaphore}"
|
||||
# Email alert env config
|
||||
SEMAPHORE_WEB_ROOT="${SEMAPHORE_WEB_ROOT:-http://127.0.0.1:8081}"
|
||||
SEMAPHORE_WEB_ROOT="${SEMAPHORE_WEB_ROOT:-http://0.0.0.0:8081}"
|
||||
# Semaphore Admin env config
|
||||
SEMAPHORE_ADMIN="${SEMAPHORE_ADMIN:-admin}"
|
||||
SEMAPHORE_ADMIN_EMAIL="${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}"
|
34
deployment/docker/dev/Dockerfile
Normal file
34
deployment/docker/dev/Dockerfile
Normal file
@ -0,0 +1,34 @@
|
||||
# Golang testing image with some tools already installed
|
||||
FROM tomwhiston/micro-golang:test-base
|
||||
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>"
|
||||
|
||||
ENV SEMAPHORE_VERSION="development" SEMAPHORE_ARCH="linux_amd64" \
|
||||
SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}" \
|
||||
APP_ROOT="/go/src/github.com/ansible-semaphore/semaphore/"
|
||||
|
||||
RUN apk add --no-cache git mysql-client python py-pip py-openssl openssl ca-certificates curl openssh-client tini nodejs nodejs-npm bash rsync && \
|
||||
apk --update add --virtual build-dependencies python-dev libffi-dev openssl-dev build-base && \
|
||||
pip install --upgrade pip cffi && \
|
||||
pip install ansible && \
|
||||
apk del build-dependencies && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
adduser -D -u 1002 -g 0 semaphore && \
|
||||
mkdir -p /go/src/github.com/ansible-semaphore/semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
chown -R semaphore:0 /go && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore && \
|
||||
ssh-keygen -t rsa -q -f "/root/.ssh/id_rsa" -N "" && \
|
||||
ssh-keyscan -H github.com > /root/.ssh/known_hosts && \
|
||||
go get -u -v github.com/go-task/task/cmd/task
|
||||
|
||||
# Copy in app source
|
||||
WORKDIR ${APP_ROOT}
|
||||
COPY . ${APP_ROOT}
|
||||
RUN deployment/docker/dev/bin/install
|
||||
|
||||
USER 1002
|
||||
EXPOSE 3000
|
||||
CMD ["task", "watch"]
|
12
deployment/docker/dev/bin/install
Executable file
12
deployment/docker/dev/bin/install
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "--> Turn off StrictKeyChecking"
|
||||
cat > /etc/ssh/ssh_config <<EOF
|
||||
Host *
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
EOF
|
||||
|
||||
echo "--> Install Semaphore entrypoint wrapper script"
|
||||
mv ./deployment/docker/common/semaphore-wrapper /usr/local/bin/semaphore-wrapper
|
||||
task deps
|
@ -8,33 +8,28 @@ services:
|
||||
MYSQL_DATABASE: semaphore
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: semaphore
|
||||
hostname: mysql
|
||||
expose:
|
||||
- 3306
|
||||
|
||||
semaphore_api:
|
||||
image: castawaylabs/semaphore
|
||||
semaphore_dev:
|
||||
image: castawaylabs/semaphore-dev:latest
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/dev/Dockerfile
|
||||
volumes:
|
||||
- "./../../../:/go/src/github.com/ansible-semaphore/semaphore:rw"
|
||||
environment:
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: semaphore
|
||||
SEMAPHORE_DB_HOST: mysql
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_PLAYBOOK_PATH: /etc/semaphore/
|
||||
SEMAPHORE_ADMIN_PASSWORD: cangetin
|
||||
SEMAPHORE_ADMIN_NAME: Default\ Administrator
|
||||
SEMAPHORE_PLAYBOOK_PATH: /etc/semaphore
|
||||
SEMAPHORE_ADMIN_PASSWORD: password
|
||||
SEMAPHORE_ADMIN_NAME: "Developer"
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
expose:
|
||||
- 3000
|
||||
SEMAPHORE_WEB_ROOT: http://0.0.0.0:3000
|
||||
ports:
|
||||
- 8081:3000
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- mysql
|
||||
|
||||
semaphore_proxy:
|
||||
build: proxy
|
||||
expose:
|
||||
- 443
|
||||
- 80
|
||||
ports:
|
||||
- 8080:80
|
||||
- 8443:443
|
29
deployment/docker/prod/Dockerfile
Normal file
29
deployment/docker/prod/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
||||
# ansible-semaphore production image
|
||||
#
|
||||
# Uses frolvlad alpine so we have access to glibc which is needed for golang
|
||||
# and when deploying in openshift
|
||||
FROM frolvlad/alpine-glibc:alpine-3.7
|
||||
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>"
|
||||
|
||||
RUN apk add --no-cache git ansible mysql-client curl openssh-client tini && \
|
||||
adduser -D -u 1001 -G root semaphore && \
|
||||
mkdir -p /tmp/semaphore && \
|
||||
mkdir -p /etc/semaphore && \
|
||||
chown -R semaphore:0 /tmp/semaphore && \
|
||||
chown -R semaphore:0 /etc/semaphore
|
||||
|
||||
COPY ./ /go/src/github.com/ansible-semaphore/semaphore
|
||||
WORKDIR /go/src/github.com/ansible-semaphore/semaphore
|
||||
|
||||
RUN apk add --no-cache -U libc-dev go nodejs && \
|
||||
./deployment/docker/prod/bin/install && \
|
||||
apk del libc-dev go nodejs && \
|
||||
rm -rf /go/* && \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
WORKDIR /home/semaphore
|
||||
USER 1001
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
CMD ["/usr/local/bin/semaphore-wrapper", "/usr/local/bin/semaphore", "--config", "/etc/semaphore/config.json"]
|
23
deployment/docker/prod/bin/install
Executable file
23
deployment/docker/prod/bin/install
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Go build environment
|
||||
export GOROOT=/usr/lib/go
|
||||
export GOPATH=/go
|
||||
export GOBIN=/go/bin
|
||||
export PATH="${PATH}:${GOBIN}"
|
||||
|
||||
# Get prerequisites for building the app
|
||||
go get -u -v github.com/go-task/task/cmd/task
|
||||
go get ./...
|
||||
|
||||
# Compile and build
|
||||
task deps
|
||||
task compile
|
||||
task build:local
|
||||
|
||||
mv ./bin/semaphore /usr/local/bin/
|
||||
chown 1001:0 /usr/local/bin/semaphore
|
||||
chmod +x /usr/local/bin/semaphore
|
||||
|
||||
mv ./deployment/docker/common/semaphore-wrapper /usr/local/bin/semaphore-wrapper
|
||||
chown 1001:0 /usr/local/bin/semaphore-wrapper
|
41
deployment/docker/prod/docker-compose.yml
Normal file
41
deployment/docker/prod/docker-compose.yml
Normal file
@ -0,0 +1,41 @@
|
||||
# This dockerfile provides an example of using the production image in a working stack
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
|
||||
mysql:
|
||||
image: mysql
|
||||
hostname: mysql
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
|
||||
MYSQL_DATABASE: semaphore
|
||||
MYSQL_USER: semaphore
|
||||
MYSQL_PASSWORD: hx4hjxqthfwbfsy5535u4agfdscm
|
||||
|
||||
semaphore:
|
||||
image: castawaylabs/semaphore:prod
|
||||
build:
|
||||
context: ./../../../
|
||||
dockerfile: ./deployment/docker/prod/Dockerfile
|
||||
environment:
|
||||
SEMAPHORE_DB_USER: semaphore
|
||||
SEMAPHORE_DB_PASS: hx4hjxqthfwbfsy5535u4agfdscm
|
||||
SEMAPHORE_DB_HOST: mysql
|
||||
SEMAPHORE_DB_PORT: 3306
|
||||
SEMAPHORE_DB: semaphore
|
||||
SEMAPHORE_PLAYBOOK_PATH: /tmp/semaphore/
|
||||
SEMAPHORE_ADMIN_PASSWORD: cangetin
|
||||
SEMAPHORE_ADMIN_NAME: admin
|
||||
SEMAPHORE_ADMIN_EMAIL: admin@localhost
|
||||
SEMAPHORE_ADMIN: admin
|
||||
depends_on:
|
||||
- mysql
|
||||
semaphore_proxy:
|
||||
image: castawaylabs/semaphore:proxy
|
||||
build:
|
||||
context: ./proxy
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
depends_on:
|
||||
- semaphore
|
44
deployment/docker/prod/goss.yaml
Normal file
44
deployment/docker/prod/goss.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
file:
|
||||
/usr/local/bin/semaphore-wrapper:
|
||||
exists: true
|
||||
owner: semaphore
|
||||
group: root
|
||||
filetype: file
|
||||
/usr/local/bin/semaphore:
|
||||
exists: true
|
||||
owner: semaphore
|
||||
group: root
|
||||
filetype: file
|
||||
package:
|
||||
ansible:
|
||||
installed: true
|
||||
curl:
|
||||
installed: true
|
||||
git:
|
||||
installed: true
|
||||
go:
|
||||
installed: false
|
||||
libc-dev:
|
||||
installed: false
|
||||
mysql-client:
|
||||
installed: true
|
||||
nodejs:
|
||||
installed: false
|
||||
openssh-client:
|
||||
installed: true
|
||||
tini:
|
||||
installed: true
|
||||
user:
|
||||
semaphore:
|
||||
exists: true
|
||||
uid: 1001
|
||||
gid: 0
|
||||
home: /home/semaphore
|
||||
command:
|
||||
semaphore:
|
||||
exit-status: 1
|
||||
stdout:
|
||||
- Cannot Find configuration! Use -c parameter to point to a JSON file generated
|
||||
by -setup.
|
||||
- 'Hint: have you run `-setup` ?'
|
||||
timeout: 10000
|
11
deployment/docker/prod/proxy/Dockerfile
Normal file
11
deployment/docker/prod/proxy/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
LABEL maintainer="Tom Whiston <tom.whiston@gmail.com>
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY cert/ /etc/nginx/cert
|
||||
COPY bin /usr/local/bin
|
||||
RUN apk add --no-cache openssl && \
|
||||
/usr/local/bin/install && \
|
||||
apk del openssl && \
|
||||
rm -rf /var/cache/apk/*
|
6
deployment/docker/prod/proxy/bin/install
Executable file
6
deployment/docker/prod/proxy/bin/install
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [ ! -f /etc/nginx/cert/privkey.pem ] && [ ! -f /etc/nginx/cert/cert.pem ]; then
|
||||
echo "--> Generating self-signed cert. This should not be used in production"
|
||||
openssl req -x509 -newkey rsa:4096 -keyout /etc/nginx/cert/privkey.pem -out /etc/nginx/cert/cert.pem -sha256 -nodes -subj "/O=Ansible Semaphore/OU=Production Test/CN=github.com\/ansible-semaphore\/semaphore"
|
||||
fi
|
0
deployment/docker/prod/proxy/cert/.gitkeep
Normal file
0
deployment/docker/prod/proxy/cert/.gitkeep
Normal file
@ -12,13 +12,22 @@ http {
|
||||
# this is necessary for us to be able to disable request buffering in all cases
|
||||
proxy_http_version 1.1;
|
||||
|
||||
upstream semaphore_api {
|
||||
server semaphore_api:3000;
|
||||
upstream semaphore {
|
||||
server semaphore:3000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name _;
|
||||
server_name _;
|
||||
|
||||
# add Strict-Transport-Security to prevent man in the middle attacks
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
|
||||
# SSL
|
||||
ssl_certificate /etc/nginx/cert/cert.pem;
|
||||
@ -37,7 +46,7 @@ http {
|
||||
chunked_transfer_encoding on;
|
||||
|
||||
location / {
|
||||
proxy_pass http://semaphore_api/;
|
||||
proxy_pass http://semaphore/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@ -49,18 +58,11 @@ http {
|
||||
}
|
||||
|
||||
location /api/ws {
|
||||
proxy_pass http://semaphore_api/api/ws;
|
||||
proxy_pass http://semaphore/api/ws;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Origin "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
rewrite ^/(.*) https://$server_name:443/$1 permanent;
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
Docker Compose
|
||||
##############
|
||||
|
||||
To run Semaphore in a simple docker configuration run the following command:
|
||||
|
||||
docker-compose up
|
||||
|
||||
You can then access Semaphore directly from the url http://localhost:8081/
|
||||
|
||||
SSL Termination Using Nginx
|
||||
###########################
|
||||
|
||||
Generate a cert, ca cert, and key file and place into `Deploy/proxy/cert/` with
|
||||
these names:
|
||||
|
||||
* `cert.pem`
|
||||
* `privkey.pem`
|
||||
* `fullchain.pem`
|
||||
|
||||
(I've used letsencrypt generated certs with success.)
|
||||
|
||||
Run `docker-compose up` and your Semaphore instance will then be at the url
|
||||
https://localhost:8443
|
||||
|
@ -1,5 +0,0 @@
|
||||
FROM nginx
|
||||
|
||||
ADD nginx.conf /etc/nginx/nginx.conf
|
||||
ADD cert/ /etc/nginx/cert
|
||||
|
@ -157,30 +157,19 @@ func loadConfig(){
|
||||
//If the confPath option has been set try to load and decode it
|
||||
if confPath != nil && len(*confPath) > 0 {
|
||||
file, err := os.Open(*confPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
exitOnConfigError(err)
|
||||
decodeConfig(file)
|
||||
} else {
|
||||
|
||||
// if no confPath look in the cwd
|
||||
cwd, err := os.Getwd()
|
||||
exitOnConfigError(err)
|
||||
cwd = cwd+"/config.json"
|
||||
confPath = &cwd
|
||||
if err == nil {
|
||||
file, err := os.Open(*confPath)
|
||||
if err == nil {
|
||||
decodeConfig(file)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("Cannot Find configuration! Use -c parameter to point to a JSON file generated by -setup.\n\n Hint: have you run `-setup` ?")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file, err := os.Open(*confPath)
|
||||
exitOnConfigError(err)
|
||||
decodeConfig(file)
|
||||
}
|
||||
fmt.Println("Using config file: "+ *confPath)
|
||||
|
||||
}
|
||||
|
||||
func validateConfig(){
|
||||
@ -210,6 +199,13 @@ func validatePort() {
|
||||
}
|
||||
}
|
||||
|
||||
func exitOnConfigError(err error){
|
||||
if err != nil {
|
||||
fmt.Println("Cannot Find configuration! Use -c parameter to point to a JSON file generated by -setup.\n\n Hint: have you run `-setup` ?")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func decodeConfig(file *os.File){
|
||||
|
Loading…
Reference in New Issue
Block a user