├── .github ├── dependabot.yml ├── linters │ ├── .hadolint.yaml │ ├── .markdown-lint.yml │ └── .yaml-lint.yml └── workflows │ ├── call-docker-build.yaml │ └── call-super-linter.yaml ├── Dockerfile ├── README.md └── httpenv.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "monthly" 8 | -------------------------------------------------------------------------------- /.github/linters/.hadolint.yaml: -------------------------------------------------------------------------------- 1 | # README: https://github.com/hadolint/hadolint 2 | 3 | # Often it's a good idea to do inline disables rather that repo-wide in this file. 4 | # Example of inline Dockerfile rules: 5 | # hadolint ignore=DL3018 6 | #RUN apk add --no-cache git 7 | 8 | # or just ignore rules repo-wide 9 | ignored: 10 | - DL3003 #ignore that we use cd sometimes 11 | - DL3006 #image pin versions 12 | - DL3008 #apt pin versions 13 | - DL3018 #apk add pin versions 14 | - DL3022 #bad rule for COPY --from 15 | - DL3028 #gem install pin versions 16 | - DL3059 #multiple consecutive runs 17 | - DL4006 #we don't need pipefail in this 18 | - SC2016 #we want single quotes sometimes 19 | 20 | 21 | # FULL TEMPLATE 22 | # failure-threshold: string # name of threshold level (error | warning | info | style | ignore | none) 23 | # format: string # Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy) 24 | # ignored: [string] # list of rules 25 | # label-schema: # See Linting Labels below for specific label-schema details 26 | # author: string # Your name 27 | # contact: string # email address 28 | # created: timestamp # rfc3339 datetime 29 | # version: string # semver 30 | # documentation: string # url 31 | # git-revision: string # hash 32 | # license: string # spdx 33 | # no-color: boolean # true | false 34 | # no-fail: boolean # true | false 35 | # override: 36 | # error: [string] # list of rules 37 | # warning: [string] # list of rules 38 | # info: [string] # list of rules 39 | # style: [string] # list of rules 40 | # strict-labels: boolean # true | false 41 | # disable-ignore-pragma: boolean # true | false 42 | # trustedRegistries: string | [string] # registry or list of registries -------------------------------------------------------------------------------- /.github/linters/.markdown-lint.yml: -------------------------------------------------------------------------------- 1 | # MD013/line-length - Line length 2 | MD013: 3 | # Number of characters, default is 80 4 | # I'm OK with long lines. All editors now have wordwrap 5 | line_length: 9999 6 | # Number of characters for headings 7 | heading_line_length: 100 8 | # check code blocks? 9 | code_blocks: false -------------------------------------------------------------------------------- /.github/linters/.yaml-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ########################################### 3 | # These are the rules used for # 4 | # linting all the yaml files in the stack # 5 | # NOTE: # 6 | # You can disable line with: # 7 | # # yamllint disable-line # 8 | ########################################### 9 | rules: 10 | braces: 11 | level: warning 12 | min-spaces-inside: 0 13 | max-spaces-inside: 0 14 | min-spaces-inside-empty: 1 15 | max-spaces-inside-empty: 5 16 | brackets: 17 | level: warning 18 | min-spaces-inside: 0 19 | max-spaces-inside: 0 20 | min-spaces-inside-empty: 1 21 | max-spaces-inside-empty: 5 22 | colons: 23 | level: warning 24 | max-spaces-before: 0 25 | max-spaces-after: 1 26 | commas: 27 | level: warning 28 | max-spaces-before: 0 29 | min-spaces-after: 1 30 | max-spaces-after: 1 31 | comments: disable 32 | comments-indentation: disable 33 | document-end: disable 34 | document-start: disable 35 | empty-lines: 36 | level: warning 37 | max: 2 38 | max-start: 0 39 | max-end: 0 40 | hyphens: 41 | level: warning 42 | max-spaces-after: 1 43 | indentation: 44 | level: warning 45 | spaces: consistent 46 | indent-sequences: true 47 | check-multi-line-strings: false 48 | key-duplicates: enable 49 | line-length: disable 50 | new-line-at-end-of-file: disable 51 | new-lines: 52 | type: unix 53 | trailing-spaces: disable -------------------------------------------------------------------------------- /.github/workflows/call-docker-build.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # template source: https://github.com/bretfisher/docker-build-workflow/blob/main/templates/call-docker-build.yaml 3 | name: Docker Build 4 | 5 | on: 6 | push: 7 | branches: 8 | - main 9 | # don't rebuild image if someone only edited unrelated files 10 | paths-ignore: 11 | - 'README.md' 12 | - '.github/linters/**' 13 | pull_request: 14 | # don't rebuild image if someone only edited unrelated files 15 | paths-ignore: 16 | - 'README.md' 17 | - '.github/linters/**' 18 | schedule: 19 | # re-run montly to keep image fresh with upstream base images 20 | - cron: '0 12 15 * *' 21 | workflow_dispatch: 22 | # run manually from Actions tab 23 | 24 | 25 | jobs: 26 | call-docker-build: 27 | 28 | name: Call Docker Build 29 | 30 | uses: bretfisher/docker-build-workflow/.github/workflows/reusable-docker-build.yaml@main 31 | 32 | permissions: 33 | contents: read 34 | packages: write # needed to push docker image to ghcr.io 35 | pull-requests: write # needed to create and update comments in PRs 36 | 37 | secrets: 38 | 39 | # Only needed if with:dockerhub-enable is true below 40 | # https://hub.docker.com/settings/security 41 | dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} 42 | dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} 43 | 44 | with: 45 | 46 | ### REQUIRED 47 | ### ENABLE ONE OR BOTH REGISTRIES 48 | ### tell docker where to push. 49 | ### NOTE if Docker Hub is set to true, you must set secrets above and also add account/repo/tags below 50 | dockerhub-enable: true 51 | ghcr-enable: true 52 | 53 | ### A list of the account/repo names for docker build. List should match what's enabled above 54 | ### defaults to: 55 | # image-names: | 56 | # ${{ github.repository }} 57 | # ghcr.io/${{ github.repository }} 58 | 59 | ### set rules for tagging images, based on special action syntax: 60 | ### https://github.com/docker/metadata-action#tags-input 61 | ### defaults to: 62 | #tag-rules: | 63 | # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} 64 | # type=raw,value=stable-{{date 'YYYYMMDDHHmmss'}},enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} 65 | # type=ref,event=pr 66 | # type=ref,event=branch 67 | # type=raw,value=gha-${{ github.run_id }} 68 | 69 | ### path to where docker should copy files into image 70 | ### defaults to root of repository (.) 71 | # context: . 72 | 73 | ### Dockerfile alternate name. Default is Dockerfile (relative to context path) 74 | # file: Containerfile 75 | 76 | ### build stage to target, defaults to empty, which builds to last stage in Dockerfile 77 | # target: 78 | 79 | ### platforms to build for 80 | ### defaults to linux/amd64 81 | ### other options: linux/amd64,linux/arm64,linux/arm/v7 82 | platforms: linux/amd64,linux/arm64 83 | 84 | ### Create a PR comment with image tags and labels 85 | ### defaults to true 86 | # comment-enable: false 87 | -------------------------------------------------------------------------------- /.github/workflows/call-super-linter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # template source: https://github.com/bretfisher/super-linter-workflow/blob/main/templates/call-super-linter.yaml 3 | name: Lint Code Base 4 | 5 | on: 6 | 7 | push: 8 | branches: [main] 9 | 10 | pull_request: 11 | 12 | jobs: 13 | call-super-linter: 14 | 15 | name: Call Super-Linter 16 | 17 | permissions: 18 | contents: read # clone the repo to lint 19 | statuses: write #read/write to repo custom statuses 20 | 21 | ### use Reusable Workflows to call my workflow remotely 22 | ### https://docs.github.com/en/actions/learn-github-actions/reusing-workflows 23 | ### you can also call workflows from inside the same repo via file path 24 | 25 | #FIXME: customize uri to point to your own forked super-linter repository 26 | uses: bretfisher/super-linter-workflow/.github/workflows/reusable-super-linter.yaml@main 27 | 28 | ### Optional settings examples 29 | 30 | # with: 31 | ### For a DevOps-focused repository. Prevents some code-language linters from running 32 | ### defaults to false 33 | # devops-only: false 34 | 35 | ### A regex to exclude files from linting 36 | ### defaults to empty 37 | # filter-regex-exclude: src/.* -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:alpine 2 | COPY httpenv.go /go 3 | RUN go build httpenv.go 4 | 5 | FROM alpine 6 | RUN addgroup -g 1000 httpenv \ 7 | && adduser -u 1000 -G httpenv -D httpenv 8 | COPY --from=0 --chown=httpenv:httpenv /go/httpenv /httpenv 9 | EXPOSE 8888 10 | # we're not changing user in this example, but you could: 11 | # USER httpenv 12 | CMD ["/httpenv"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # httpenv 2 | Tiny HTTP server showing the environment variables on TCP 8888. 3 | 4 | [![Lint Code Base](https://github.com/BretFisher/httpenv/actions/workflows/call-super-linter.yaml/badge.svg)](https://github.com/BretFisher/httpenv/actions/workflows/call-super-linter.yaml) 5 | [![Docker Build](https://github.com/BretFisher/httpenv/actions/workflows/call-docker-build.yaml/badge.svg)](https://github.com/BretFisher/httpenv/actions/workflows/call-docker-build.yaml) 6 | 7 | 8 | Images for `linux/x86_64` (amd64), `linux/arm64` (v8), and `linux/arm/v7` 9 | 10 | This can be used for various container learnings like how DNS round-robin works, rolling updates, etc. 11 | It can be easier to use than something large and resource hungary like elasticsearch, while still providing 12 | a way to check which container you're seeing in browser (or `curl`) by viewing the env vars it returns in HTTP. 13 | 14 | Run it from Docker Hub on host port 8888: 15 | 16 | `docker run -d -p 8888:8888 bretfisher/httpenv` 17 | 18 | or from GitHub Container Registry (GHCR) with: 19 | 20 | `docker run -d -p 8888:8888 ghcr.io/bretfisher/httpenv` 21 | 22 | If you `curl` it, you should get back its environment variables, including the container name: 23 | 24 | ```shell 25 | curl http://localhost:8888 26 | 27 | {"HOME":"/root","HOSTNAME":"c9d8d26bda3a","PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}``` 28 | -------------------------------------------------------------------------------- /httpenv.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( 3 | "encoding/json" 4 | "fmt" 5 | "net/http" 6 | "os" 7 | "strings" 8 | ) 9 | func serve(w http.ResponseWriter, r *http.Request) { 10 | env := map[string]string{} 11 | for _, keyval := range os.Environ() { 12 | keyval := strings.SplitN(keyval, "=", 2) 13 | env[keyval[0]] = keyval[1] 14 | } 15 | bytes, err := json.Marshal(env) 16 | if err != nil { 17 | w.Write([]byte("{}")) 18 | return 19 | } 20 | w.Write([]byte(bytes)) 21 | } 22 | func main() { 23 | fmt.Printf("Starting httpenv listening on port 8888.\n") 24 | http.HandleFunc("/", serve) 25 | if err := http.ListenAndServe(":8888", nil); err != nil { 26 | panic(err) 27 | } 28 | } 29 | 30 | --------------------------------------------------------------------------------