Initial docker registry stack lifted from personal projects
This commit is contained in:
parent
6900486c53
commit
79931a1203
9 changed files with 269 additions and 0 deletions
products/docker_registry
43
products/docker_registry/auth.tf
Normal file
43
products/docker_registry/auth.tf
Normal file
|
@ -0,0 +1,43 @@
|
|||
locals {
|
||||
registry_users = {
|
||||
for user in var.registry_users : user.username =>
|
||||
user.password == null ? random_password.registry_users[user.username].result : user.password
|
||||
}
|
||||
# For each user, construct a htpasswd line
|
||||
registry_user_pass_pairs = [
|
||||
for user in local.registry_users : "${user}:${htpasswd_password.registry_users[user].bcrypt}"
|
||||
]
|
||||
registry_htpasswd = "${join("\n", local.registry_user_pass_pairs)}\n"
|
||||
}
|
||||
resource "random_password" "registry_users" {
|
||||
for_each = toset(local.registry_users)
|
||||
length = 32
|
||||
special = false
|
||||
}
|
||||
resource "random_password" "salt" {
|
||||
for_each = toset(local.registry_users)
|
||||
length = 8
|
||||
special = false
|
||||
}
|
||||
resource "htpasswd_password" "registry_users" {
|
||||
for_each = random_password.registry_users
|
||||
password = each.value.result
|
||||
salt = random_password.salt[each.key].result
|
||||
}
|
||||
resource "docker_config" "docker_registry_htpasswd" {
|
||||
name = "docker-registry-htpasswd-${replace(timestamp(), ":", ".")}"
|
||||
data = base64encode(local.registry_htpasswd)
|
||||
lifecycle {
|
||||
ignore_changes = [name]
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
resource "local_file" "docker_registry_htpasswd" {
|
||||
content = local.registry_htpasswd
|
||||
filename = "${path.root}/.debug/docker-registry/htpasswd"
|
||||
}
|
||||
|
||||
resource "random_password" "http_secret" {
|
||||
for_each = toset(var.registry_users)
|
||||
length = 16
|
||||
}
|
52
products/docker_registry/inputs.tf
Normal file
52
products/docker_registry/inputs.tf
Normal file
|
@ -0,0 +1,52 @@
|
|||
variable "placement_constraints" {
|
||||
default = []
|
||||
type = list(string)
|
||||
description = "Docker Swarm placement constraints"
|
||||
}
|
||||
variable "stack_name" {
|
||||
type = string
|
||||
default = "docker-registry"
|
||||
description = "The name of the stack"
|
||||
}
|
||||
variable "registry_users" {
|
||||
type = list(object({
|
||||
username = string
|
||||
password = optional(string)
|
||||
}))
|
||||
description = "A list of users to create in the registry"
|
||||
}
|
||||
variable "enable_delete" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "Enable the delete feature in the registry"
|
||||
}
|
||||
variable "s3_accesskey" {
|
||||
type = string
|
||||
description = "The access key for the S3 bucket"
|
||||
}
|
||||
variable "s3_secretkey" {
|
||||
type = string
|
||||
description = "The secret key for the S3 bucket"
|
||||
}
|
||||
variable "s3_region" {
|
||||
type = string
|
||||
description = "The region for the S3 bucket"
|
||||
}
|
||||
variable "s3_regionendpoint" {
|
||||
type = string
|
||||
description = "The region endpoint for the S3 bucket"
|
||||
default = null
|
||||
}
|
||||
variable "s3_forcepathstyle" {
|
||||
type = bool
|
||||
description = "Force path style for the S3 bucket"
|
||||
default = false
|
||||
}
|
||||
variable "s3_bucket" {
|
||||
type = string
|
||||
description = "The bucket name for the S3 bucket"
|
||||
}
|
||||
variable "domain" {
|
||||
type = string
|
||||
description = "The domain for the registry"
|
||||
}
|
15
products/docker_registry/janitor.tf
Normal file
15
products/docker_registry/janitor.tf
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
module "docker_registry_janitor" {
|
||||
source = "../../docker/service"
|
||||
stack_name = var.stack_name
|
||||
service_name = "janitor"
|
||||
image = "registry:2"
|
||||
configs = {
|
||||
"/etc/docker/registry/config.yml" = yamlencode(local.registry_config_yaml)
|
||||
"/etc/docker/registry/htpasswd" = local.registry_htpasswd
|
||||
}
|
||||
restart_policy = "any"
|
||||
restart_delay = "6h"
|
||||
placement_constraints = var.placement_constraints
|
||||
networks = [module.registry_network]
|
||||
}
|
4
products/docker_registry/network.tf
Normal file
4
products/docker_registry/network.tf
Normal file
|
@ -0,0 +1,4 @@
|
|||
module "registry_network" {
|
||||
source = "../../docker/network"
|
||||
stack_name = "registry"
|
||||
}
|
7
products/docker_registry/outputs.tf
Normal file
7
products/docker_registry/outputs.tf
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
# Outputs
|
||||
output "registry_users" {
|
||||
value = {
|
||||
for user in local.registry_users : user => nonsensitive(random_password.registry_users[user].result)
|
||||
}
|
||||
}
|
6
products/docker_registry/redis.tf
Normal file
6
products/docker_registry/redis.tf
Normal file
|
@ -0,0 +1,6 @@
|
|||
module "docker_registry_redis" {
|
||||
source = "../../products/redis"
|
||||
stack_name = var.stack_name
|
||||
networks = [module.registry_network]
|
||||
placement_constraints = var.placement_constraints
|
||||
}
|
84
products/docker_registry/registry.tf
Normal file
84
products/docker_registry/registry.tf
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
locals{
|
||||
registry_config_yaml = {
|
||||
version = 0.1
|
||||
storage = {
|
||||
s3 = {
|
||||
accesskey = var.s3_accesskey
|
||||
secretkey = var.s3_secretkey
|
||||
region = var.s3_region
|
||||
regionendpoint = var.s3_regionendpoint
|
||||
forcepathstyle = var.s3_forcepathstyle
|
||||
bucket = var.s3_bucket
|
||||
}
|
||||
delete = {
|
||||
enabled = var.enable_delete
|
||||
}
|
||||
}
|
||||
http = {
|
||||
addr = "0.0.0.0:5000"
|
||||
secret = random_password.http_secret.result
|
||||
host = var.domain
|
||||
headers = {
|
||||
Access-Control-Allow-Origin = ["https://${var.domain}", ] // @todo add s3 domain here
|
||||
Access-Control-Allow-Methods = ["HEAD", "GET", "DELETE", "OPTIONS"]
|
||||
Access-Control-Allow-Credentials = ["true"]
|
||||
Access-Control-Allow-Headers = ["Authorization", "Cache-Control", "Accept"]
|
||||
Access-Control-Expose-Headers = ["Docker-Content-Digest"]
|
||||
}
|
||||
}
|
||||
redis = {
|
||||
addrs = ["${module.docker_registry_redis.service_name}:6379"]
|
||||
password = module.docker_registry_redis.auth
|
||||
db = 0
|
||||
}
|
||||
validation = {
|
||||
manifests = {
|
||||
urls = {
|
||||
allow = [
|
||||
"^https?://${var.domain}/"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
auth = {
|
||||
htpasswd = {
|
||||
realm = "Registry Realm"
|
||||
path = "/etc/docker/registry/htpasswd"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Configuration file
|
||||
module "docker_registry_config" {
|
||||
source = "../../docker/config"
|
||||
name = "docker-registry-config"
|
||||
stack_name = var.stack_name
|
||||
value = yamlencode(local.registry_config_yaml)
|
||||
}
|
||||
resource "local_file" "docker_registry_config_yml" {
|
||||
content = yamlencode(local.registry_config_yaml)
|
||||
filename = "${path.root}/.debug/docker-registry/config.yml"
|
||||
}
|
||||
|
||||
# Registry Service
|
||||
module "docker_registry" {
|
||||
source = "../../docker/service"
|
||||
stack_name = var.stack_name
|
||||
service_name = "registry"
|
||||
image = "registry:2"
|
||||
configs = {
|
||||
"/etc/docker/registry/config.yml" = nonsensitive(yamlencode(local.registry_config_yaml))
|
||||
"/etc/docker/registry/htpasswd" = nonsensitive(local.registry_htpasswd)
|
||||
}
|
||||
restart_policy = "on-failure"
|
||||
placement_constraints = var.placement_constraints
|
||||
networks = [module.registry_network]
|
||||
ports = [
|
||||
{
|
||||
host = 5000
|
||||
container = 5000
|
||||
}
|
||||
]
|
||||
}
|
19
products/docker_registry/terraform.tf
Normal file
19
products/docker_registry/terraform.tf
Normal file
|
@ -0,0 +1,19 @@
|
|||
terraform {
|
||||
required_version = "~> 1.6"
|
||||
required_providers {
|
||||
docker = {
|
||||
source = "kreuzwerker/docker"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.5"
|
||||
}
|
||||
htpasswd = {
|
||||
source = "loafoe/htpasswd"
|
||||
version = "~> 1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
39
products/docker_registry/ui.tf
Normal file
39
products/docker_registry/ui.tf
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
# Registry UI
|
||||
module "docker_registry_ui" {
|
||||
source = "../../docker/service"
|
||||
stack_name = var.stack_name
|
||||
service_name = "ui"
|
||||
image = "joxit/docker-registry-ui:main"
|
||||
environment_variables = {
|
||||
SINGLE_REGISTRY = "true"
|
||||
REGISTRY_TITLE = "Grey.ooo Docker Registry"
|
||||
NGINX_PROXY_PASS_URL = "http://${module.docker_registry.docker_service.name}:5000"
|
||||
DELETE_IMAGES = "true"
|
||||
SHOW_CONTENT_DIGEST = "true"
|
||||
SHOW_CATALOG_NB_TAGS = "true"
|
||||
CATALOG_MIN_BRANCHES = 1
|
||||
CATALOG_MAX_BRANCHES = 1
|
||||
TAGLIST_PAGE_SIZE = 100
|
||||
REGISTRY_SECURED = false
|
||||
CATALOG_ELEMENTS_LIMIT = 1000
|
||||
}
|
||||
networks = [module.registry_network, var.traefik.network, ]
|
||||
placement_constraints = var.placement_constraints
|
||||
traefik = var.traefik
|
||||
}
|
||||
|
||||
variable "traefik" {
|
||||
default = null
|
||||
type = object({
|
||||
domain = string
|
||||
port = optional(number)
|
||||
ssl = optional(bool, false)
|
||||
rule = optional(string)
|
||||
network = optional(object({
|
||||
id = string
|
||||
name = string
|
||||
}))
|
||||
})
|
||||
description = "Whether to enable traefik for the service."
|
||||
}
|
Loading…
Reference in a new issue