Cleanup image building code, refactored, fewer exposed ports, templated files in runtime
This commit is contained in:
parent
4a6d77d0f4
commit
6a678944a0
@ -1,5 +1,5 @@
|
|||||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build
|
||||||
RUN apk add crystal shards yaml-dev openssl-dev zlib-dev
|
RUN apk add crystal shards yaml-dev openssl-dev zlib-dev libxml2-dev
|
||||||
RUN addgroup -S app && adduser app -S -G app
|
RUN addgroup -S app && adduser app -S -G app
|
||||||
WORKDIR /home/app
|
WORKDIR /home/app
|
||||||
COPY shard.yml ./
|
COPY shard.yml ./
|
||||||
@ -10,7 +10,7 @@ RUN shards build -d --error-trace
|
|||||||
RUN strip bin/faaso-daemon
|
RUN strip bin/faaso-daemon
|
||||||
|
|
||||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship
|
||||||
RUN apk add tinyproxy multirun openssl zlib yaml pcre2 gc libevent libgcc
|
RUN apk add tinyproxy multirun openssl zlib yaml pcre2 gc libevent libgcc libxml2
|
||||||
|
|
||||||
# Unprivileged user
|
# Unprivileged user
|
||||||
RUN addgroup -S app && adduser app -S -G app
|
RUN addgroup -S app && adduser app -S -G app
|
||||||
|
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ build: shard.yml $(wildcard src/**/*cr)
|
|||||||
proxy-image: build
|
proxy-image: build
|
||||||
docker build . -t faaso-proxy --no-cache
|
docker build . -t faaso-proxy --no-cache
|
||||||
start-proxy:
|
start-proxy:
|
||||||
docker run --network=faaso-net -v /var/run/docker.sock:/var/run/docker.sock -p 8888:8888 -p 3000:3000 faaso-proxy
|
docker run --network=faaso-net -v /var/run/docker.sock:/var/run/docker.sock -p 8888:8888 faaso-proxy
|
||||||
|
|
||||||
|
|
||||||
.PHONY: build proxy-image start-proxy
|
.PHONY: build proxy-image start-proxy
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build
|
||||||
|
|
||||||
RUN apk update && apk upgrade && apk add crystal shards openssl-dev zlib-dev && apk cache clean
|
RUN apk update && apk upgrade && apk add crystal shards openssl-dev zlib-dev {{ ship_packages | join(" ") }} {{ devel_packages | join(" ") }} && apk cache clean
|
||||||
|
|
||||||
WORKDIR /home/app
|
WORKDIR /home/app
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ RUN shards build --release
|
|||||||
RUN strip bin/*
|
RUN strip bin/*
|
||||||
|
|
||||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship
|
||||||
RUN apk update && apk upgrade && apk add openssl pcre2 libgcc gc libevent curl && apk cache clean
|
RUN apk update && apk upgrade && apk add openssl pcre2 libgcc gc libevent curl {{ ship_packages | join " " }} && apk cache clean
|
||||||
RUN addgroup -S app && adduser app -S -G app
|
RUN addgroup -S app && adduser app -S -G app
|
||||||
|
|
||||||
WORKDIR /home/app
|
WORKDIR /home/app
|
||||||
@ -19,4 +19,4 @@ USER app
|
|||||||
COPY --from=build /home/app/bin/function .
|
COPY --from=build /home/app/bin/function .
|
||||||
|
|
||||||
CMD ["./function"]
|
CMD ["./function"]
|
||||||
HEALTHCHECK CMD curl --fail http://localhost:3000/ping || exit 1
|
HEALTHCHECK {{ healthcheck_options }} CMD {{ healthcheck_command }}
|
@ -8,6 +8,10 @@ shards:
|
|||||||
git: https://github.com/mrrooijen/commander.git
|
git: https://github.com/mrrooijen/commander.git
|
||||||
version: 0.4.0
|
version: 0.4.0
|
||||||
|
|
||||||
|
crinja:
|
||||||
|
git: https://github.com/straight-shoota/crinja.git
|
||||||
|
version: 0.8.1
|
||||||
|
|
||||||
crystar:
|
crystar:
|
||||||
git: https://github.com/naqvis/crystar.git
|
git: https://github.com/naqvis/crystar.git
|
||||||
version: 0.4.0
|
version: 0.4.0
|
||||||
@ -24,10 +28,6 @@ shards:
|
|||||||
git: https://github.com/kemalcr/kemal.git
|
git: https://github.com/kemalcr/kemal.git
|
||||||
version: 1.5.0
|
version: 1.5.0
|
||||||
|
|
||||||
kiwi:
|
|
||||||
git: https://github.com/ralsina/kiwi.git
|
|
||||||
version: 0.1.0+git.commit.65059b87771238593a28b2b8b9fdf77d8e2b9e89
|
|
||||||
|
|
||||||
radix:
|
radix:
|
||||||
git: https://github.com/luislavena/radix.git
|
git: https://github.com/luislavena/radix.git
|
||||||
version: 0.4.1
|
version: 0.4.1
|
||||||
|
@ -23,3 +23,5 @@ dependencies:
|
|||||||
github: mrrooijen/commander
|
github: mrrooijen/commander
|
||||||
kemal:
|
kemal:
|
||||||
github: kemalcr/kemal
|
github: kemalcr/kemal
|
||||||
|
crinja:
|
||||||
|
github: straight-shoota/crinja
|
30
src/faaso.cr
30
src/faaso.cr
@ -2,7 +2,6 @@ require "./funko.cr"
|
|||||||
require "commander"
|
require "commander"
|
||||||
require "docr"
|
require "docr"
|
||||||
require "docr/utils.cr"
|
require "docr/utils.cr"
|
||||||
require "file_utils"
|
|
||||||
require "uuid"
|
require "uuid"
|
||||||
|
|
||||||
# Functions as a Service, Ops!
|
# Functions as a Service, Ops!
|
||||||
@ -36,38 +35,13 @@ module Faaso
|
|||||||
def run
|
def run
|
||||||
funkos = Funko.from_paths(@arguments)
|
funkos = Funko.from_paths(@arguments)
|
||||||
funkos.each do |funko|
|
funkos.each do |funko|
|
||||||
# FIXME: refactor lots of this into the Funko class
|
|
||||||
# Create temporary build location
|
# Create temporary build location
|
||||||
tmp_dir = Path.new("tmp", UUID.random.to_s)
|
tmp_dir = Path.new("tmp", UUID.random.to_s)
|
||||||
Dir.mkdir_p(tmp_dir) unless File.exists? tmp_dir
|
Dir.mkdir_p(tmp_dir) unless File.exists? tmp_dir
|
||||||
|
funko.prepare_build tmp_dir
|
||||||
# Copy runtime if requested
|
|
||||||
if !funko.runtime.nil?
|
|
||||||
runtime_dir = Path.new("runtimes", funko.runtime.to_s)
|
|
||||||
if !File.exists? runtime_dir
|
|
||||||
puts "Error: runtime #{funko.runtime} not found"
|
|
||||||
next
|
|
||||||
end
|
|
||||||
Dir.glob("#{runtime_dir}/*").each { |src|
|
|
||||||
FileUtils.cp_r(src, tmp_dir)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Copy funko
|
|
||||||
if funko.path.empty?
|
|
||||||
puts "Internal error: empty funko path for #{funko.name}"
|
|
||||||
next
|
|
||||||
end
|
|
||||||
Dir.glob("#{funko.path}/*").each { |src|
|
|
||||||
FileUtils.cp_r(src, tmp_dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
puts "Building function... #{funko.name} in #{tmp_dir}"
|
puts "Building function... #{funko.name} in #{tmp_dir}"
|
||||||
|
funko.build tmp_dir
|
||||||
docker_api = Docr::API.new(Docr::Client.new)
|
|
||||||
docker_api.images.build(
|
|
||||||
context: tmp_dir.to_s,
|
|
||||||
tags: ["#{funko.name}:latest"]) { }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
74
src/funko.cr
74
src/funko.cr
@ -1,3 +1,5 @@
|
|||||||
|
require "crinja"
|
||||||
|
require "file_utils"
|
||||||
require "yaml"
|
require "yaml"
|
||||||
|
|
||||||
# A funko, built from its source metadata
|
# A funko, built from its source metadata
|
||||||
@ -10,23 +12,30 @@ class Funko
|
|||||||
# if Nil, it has no template whatsoever
|
# if Nil, it has no template whatsoever
|
||||||
property runtime : (String | Nil)? = nil
|
property runtime : (String | Nil)? = nil
|
||||||
|
|
||||||
# Port of the funko process (optional, default is 3000)
|
# Extra packages shipped with the Docker image
|
||||||
property port : UInt32? = 3000
|
property ship_packages : Array(String) = [] of String
|
||||||
|
|
||||||
# Extra packages, passed as EXTRA_PACKAGES argument
|
# Extra packages used only in the *build* image
|
||||||
# to the Dockerfile, use it for installing things in
|
property devel_packages : Array(String) = [] of String
|
||||||
# the SHIPPED docker image
|
|
||||||
property extra_packages : Array(String)?
|
|
||||||
|
|
||||||
# Extra packages, passed as DEVEL_PACKAGES argument
|
|
||||||
# to the Dockerfile, use it for installing things in
|
|
||||||
# the docker stage used to build the code
|
|
||||||
property devel_packages : Array(String)?
|
|
||||||
|
|
||||||
# Where this is located in the filesystem
|
# Where this is located in the filesystem
|
||||||
@[YAML::Field(ignore: true)]
|
@[YAML::Field(ignore: true)]
|
||||||
property path : String = ""
|
property path : String = ""
|
||||||
|
|
||||||
|
# Healthcheck properties
|
||||||
|
property healthcheck_options : String = "--interval=1m --timeout=2s --start-period=2s --retries=3"
|
||||||
|
property healthcheck_command : String = "curl --fail http://localhost:3000/ping || exit 1"
|
||||||
|
|
||||||
|
def _to_context
|
||||||
|
{
|
||||||
|
"name" => name,
|
||||||
|
"ship_packages" => ship_packages,
|
||||||
|
"devel_packages" => devel_packages,
|
||||||
|
"healthcheck_options" => healthcheck_options,
|
||||||
|
"healthcheck_command" => healthcheck_command,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# Create an Array of funkos from an Array of folders containing definitions
|
# Create an Array of funkos from an Array of folders containing definitions
|
||||||
def self.from_paths(paths : Array(String | Path)) : Array(Funko)
|
def self.from_paths(paths : Array(String | Path)) : Array(Funko)
|
||||||
paths.map { |path| Path.new(path, "funko.yml") }
|
paths.map { |path| Path.new(path, "funko.yml") }
|
||||||
@ -38,6 +47,42 @@ class Funko
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Setup the target directory `path` with all the files needed
|
||||||
|
# to build a docker image
|
||||||
|
def prepare_build(path : Path)
|
||||||
|
# Copy runtime if requested
|
||||||
|
if !runtime.nil?
|
||||||
|
runtime_dir = Path.new("runtimes", runtime.as(String))
|
||||||
|
raise Exception.new("Error: runtime #{runtime} not found for funko #{name} in #{path}") unless File.exists?(runtime_dir)
|
||||||
|
Dir.glob("#{runtime_dir}/*").each { |src|
|
||||||
|
FileUtils.cp_r(src, path)
|
||||||
|
}
|
||||||
|
# Replace templates with processed files
|
||||||
|
context = _to_context
|
||||||
|
Dir.glob("#{path}/**/*.j2").each { |template|
|
||||||
|
dst = template[..-4]
|
||||||
|
File.open(dst, "w") do |file|
|
||||||
|
file << Crinja.render(File.read(template), context)
|
||||||
|
end
|
||||||
|
File.delete template
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Copy funko
|
||||||
|
raise Exception.new("Internal error: empty funko path for #{name}") if self.path.empty?
|
||||||
|
Dir.glob("#{self.path}/*").each { |src|
|
||||||
|
FileUtils.cp_r(src, path)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Build image using docker in path previously prepared using `prepare_build`
|
||||||
|
def build(path : Path)
|
||||||
|
docker_api = Docr::API.new(Docr::Client.new)
|
||||||
|
docker_api.images.build(
|
||||||
|
context: path.to_s,
|
||||||
|
tags: ["#{name}:latest"]) { }
|
||||||
|
end
|
||||||
|
|
||||||
# Return a list of image IDs for this funko, most recent first
|
# Return a list of image IDs for this funko, most recent first
|
||||||
def image_history
|
def image_history
|
||||||
docker_api = Docr::API.new(Docr::Client.new)
|
docker_api = Docr::API.new(Docr::Client.new)
|
||||||
@ -112,15 +157,8 @@ class Funko
|
|||||||
image: "#{name}:latest",
|
image: "#{name}:latest",
|
||||||
hostname: name,
|
hostname: name,
|
||||||
# Port in the container side
|
# Port in the container side
|
||||||
# FIXME: Maybe don't need this now we are using the proxy
|
|
||||||
exposed_ports: {"#{port}/tcp" => {} of String => String},
|
|
||||||
host_config: Docr::Types::HostConfig.new(
|
host_config: Docr::Types::HostConfig.new(
|
||||||
network_mode: "faaso-net",
|
network_mode: "faaso-net",
|
||||||
# Also probably not needed anymore
|
|
||||||
port_bindings: {"#{port}/tcp" => [Docr::Types::PortBinding.new(
|
|
||||||
host_port: "", # Host port, empty means random
|
|
||||||
host_ip: "127.0.0.1", # Host IP
|
|
||||||
)]}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user