commit e6b9c0f652ff929ab38c3b2ad0fabff6d37740cc Author: pro100ton Date: Sat Nov 2 15:32:43 2024 +0300 Docker deep dive book materials diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4d92b67 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ddd-book"] + path = ddd-book + url = https://github.com/nigelpoulton/ddd-book.git diff --git a/ddd-book/README.md b/ddd-book/README.md new file mode 100644 index 0000000..51a9856 --- /dev/null +++ b/ddd-book/README.md @@ -0,0 +1,7 @@ +# Docker Deep Dive + +This repos contains the apps and config files for the 2023 edition of Docker Deep Dive. + +### Folders and container images + +**multi-container:** Compose app and app code. Used to build `` diff --git a/ddd-book/multi-contianer/.DS_Store b/ddd-book/multi-contianer/.DS_Store new file mode 100644 index 0000000..99e9a78 Binary files /dev/null and b/ddd-book/multi-contianer/.DS_Store differ diff --git a/ddd-book/multi-contianer/Dockerfile b/ddd-book/multi-contianer/Dockerfile new file mode 100644 index 0000000..28a19c6 --- /dev/null +++ b/ddd-book/multi-contianer/Dockerfile @@ -0,0 +1,16 @@ +# Base image +FROM python:alpine + +# Copy app, templates and views +COPY . /app + +# Set working directory for subsequent commands +WORKDIR /app + +# Install dependencies +RUN pip install -r requirements.txt + +EXPOSE 8080 + +# Command to run when container starts +ENTRYPOINT ["python", "app/app.py"] diff --git a/ddd-book/multi-contianer/README.md b/ddd-book/multi-contianer/README.md new file mode 100644 index 0000000..ecb942a --- /dev/null +++ b/ddd-book/multi-contianer/README.md @@ -0,0 +1,7 @@ +# Simple counter-app for demonstrating Docker Compose +Flask app that displays SAFC image and counts page refreshes in Redis backend. + +**Used in:** +- Getting Started with Docker video training course (2023 edition) + +**Pre-built image:** [Docker Hub](https://hub.docker.com/repository/docker/nigelpoulton/gsd/) **tag:** `compose2023` diff --git a/ddd-book/multi-contianer/app/.DS_Store b/ddd-book/multi-contianer/app/.DS_Store new file mode 100644 index 0000000..722c249 Binary files /dev/null and b/ddd-book/multi-contianer/app/.DS_Store differ diff --git a/ddd-book/multi-contianer/app/app.py b/ddd-book/multi-contianer/app/app.py new file mode 100644 index 0000000..b932428 --- /dev/null +++ b/ddd-book/multi-contianer/app/app.py @@ -0,0 +1,25 @@ +import time +import redis +from flask import Flask, render_template + +app = Flask(__name__) +cache = redis.Redis(host='redis', port=6379) + +def get_hit_count(): + retries = 5 + while True: + try: + return cache.incr('hits') + except redis.exceptions.ConnectionError as exc: + if retries == 0: + raise exc + retries -= 1 + time.sleep(0.5) + +@app.route("/") +def index(): + count = get_hit_count() + return render_template('index.html', count=count) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=8080, debug=True) diff --git a/ddd-book/multi-contianer/app/static/.DS_Store b/ddd-book/multi-contianer/app/static/.DS_Store new file mode 100644 index 0000000..5ccf80d Binary files /dev/null and b/ddd-book/multi-contianer/app/static/.DS_Store differ diff --git a/ddd-book/multi-contianer/app/static/css/.DS_Store b/ddd-book/multi-contianer/app/static/css/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/ddd-book/multi-contianer/app/static/css/.DS_Store differ diff --git a/ddd-book/multi-contianer/app/static/css/main.css b/ddd-book/multi-contianer/app/static/css/main.css new file mode 100644 index 0000000..6af7732 --- /dev/null +++ b/ddd-book/multi-contianer/app/static/css/main.css @@ -0,0 +1,81 @@ +body { + margin: 0; + padding: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #444; +} +/* + * Formatting the header area + */ +header { + background-color: #f80000; + height: 35px; + width: 100%; + opacity: .9; + margin-bottom: 10px; +} +header h1.logo { + margin: 0; + font-size: 1.7em; + color: #fff; + text-align: center; +} +header h1.logo:hover { + color: #fff; + text-decoration: none; +} +/* + * Centering the body content + */ +.container { + width: 1200px; + margin: 0 auto; +} +div.home { + padding: 10px 0 30px 0; + background-color: #E6E6FA; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +div.about { + padding: 10px 0 30px 0; + background-color: #E6E6FA; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +h2 { + font-size: 2.2em; + margin-top: 40px; + text-align: center; + letter-spacing: -2px; +} +h3 { + font-size: 2em; + font-weight: 150; + margin-top: 30px; + text-align: center; + letter-spacing: -1px; + color: #282626; +} +.menu { + float: right; + margin-top: 8px; +} +.menu li { + display: inline; +} +.menu li + li { + margin-left: 35px; +} +.menu li a { + color: #444; + text-decoration: none; +} +.center { + display: block; + margin-left: auto; + margin-right: auto; + width: 50%; +} \ No newline at end of file diff --git a/ddd-book/multi-contianer/app/static/images/.DS_Store b/ddd-book/multi-contianer/app/static/images/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/ddd-book/multi-contianer/app/static/images/.DS_Store differ diff --git a/ddd-book/multi-contianer/app/static/images/image.png b/ddd-book/multi-contianer/app/static/images/image.png new file mode 100644 index 0000000..3338b3b Binary files /dev/null and b/ddd-book/multi-contianer/app/static/images/image.png differ diff --git a/ddd-book/multi-contianer/app/templates/error.html b/ddd-book/multi-contianer/app/templates/error.html new file mode 100644 index 0000000..1d7761b --- /dev/null +++ b/ddd-book/multi-contianer/app/templates/error.html @@ -0,0 +1,10 @@ + + + + + Error page + + + Throwing an error + + diff --git a/ddd-book/multi-contianer/app/templates/index.html b/ddd-book/multi-contianer/app/templates/index.html new file mode 100644 index 0000000..199fc90 --- /dev/null +++ b/ddd-book/multi-contianer/app/templates/index.html @@ -0,0 +1,20 @@ + + + + + Suck my pipa + + + + NP logo +
+
+

Suck my pipa

+
+
+
+

Hit refresh if you think Sunderland AFC are the greatest football team in the world ;-)

+

You've refreshed bibas {{ count }} times

+
+ + diff --git a/ddd-book/multi-contianer/compose.yaml b/ddd-book/multi-contianer/compose.yaml new file mode 100644 index 0000000..ea34379 --- /dev/null +++ b/ddd-book/multi-contianer/compose.yaml @@ -0,0 +1,24 @@ +networks: + counter-net: + +volumes: + counter-vol: + +services: + web-fe: + build: . + command: python app.py + ports: + - target: 8080 + published: 5001 + networks: + - counter-net + volumes: + - type: volume + source: counter-vol + target: /app + redis: + image: "redis:alpine" + networks: + counter-net: + diff --git a/ddd-book/multi-contianer/requirements.txt b/ddd-book/multi-contianer/requirements.txt new file mode 100644 index 0000000..770a967 --- /dev/null +++ b/ddd-book/multi-contianer/requirements.txt @@ -0,0 +1,3 @@ +flask +redis +jinja2 \ No newline at end of file diff --git a/ddd-book/multi-stage/.DS_Store b/ddd-book/multi-stage/.DS_Store new file mode 100644 index 0000000..8213706 Binary files /dev/null and b/ddd-book/multi-stage/.DS_Store differ diff --git a/ddd-book/multi-stage/Dockerfile b/ddd-book/multi-stage/Dockerfile new file mode 100644 index 0000000..35e9cee --- /dev/null +++ b/ddd-book/multi-stage/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:1.20-alpine AS base +WORKDIR /src +COPY go.mod go.sum . +RUN go mod download +COPY . . + +FROM base AS build-client +RUN go build -o /bin/client ./cmd/client + +FROM base AS build-server +RUN go build -o /bin/server ./cmd/server + +FROM scratch AS prod +COPY --from=build-client /bin/client /bin/ +COPY --from=build-server /bin/server /bin/ +ENTRYPOINT [ "/bin/server" ] diff --git a/ddd-book/multi-stage/Dockerfile-final b/ddd-book/multi-stage/Dockerfile-final new file mode 100644 index 0000000..08ff162 --- /dev/null +++ b/ddd-book/multi-stage/Dockerfile-final @@ -0,0 +1,19 @@ +FROM golang:1.20-alpine AS base +WORKDIR /src +COPY go.mod go.sum . +RUN go mod download +COPY . . + +FROM base AS build-client +RUN go build -o /bin/client ./cmd/client + +FROM base AS build-server +RUN go build -o /bin/server ./cmd/server + +FROM scratch AS prod-client +COPY --from=build-client /bin/client /bin/ +ENTRYPOINT [ "/bin/client" ] + +FROM scratch AS prod-server +COPY --from=build-server /bin/server /bin/ +ENTRYPOINT [ "/bin/server" ] diff --git a/ddd-book/multi-stage/README.md b/ddd-book/multi-stage/README.md new file mode 100644 index 0000000..5f6e314 --- /dev/null +++ b/ddd-book/multi-stage/README.md @@ -0,0 +1,9 @@ +# Multi-stage builds + +This example is based on the [Docker sample buildme repo])(https://github.com/dockersamples/buildme) and contains a simple client server app written on Go. + +## App code + +The app code is in the `cmd` directory but you don't need to interact with the app code or be a Go programmer. + + diff --git a/ddd-book/multi-stage/cmd/client/main.go b/ddd-book/multi-stage/cmd/client/main.go new file mode 100644 index 0000000..4c98781 --- /dev/null +++ b/ddd-book/multi-stage/cmd/client/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "os" +) + +func main() { + err := ping() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + err = start() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } +} diff --git a/ddd-book/multi-stage/cmd/client/request.go b/ddd-book/multi-stage/cmd/client/request.go new file mode 100644 index 0000000..6bf0d59 --- /dev/null +++ b/ddd-book/multi-stage/cmd/client/request.go @@ -0,0 +1,39 @@ +package main + +import ( + "errors" + "fmt" + "io" + "net/http" + "net/url" + "os" +) + +var baseURL string = "http://localhost" +var port string = "3000" +var requestUrl string = fmt.Sprintf("%s:%s?s=", baseURL, port) + +func ping() error { + res, err := http.Get(requestUrl) + if err != nil { + return err + } + if res.StatusCode != http.StatusOK { + return errors.New("failed to establish server connection") + } + return nil +} + +func getTranslation(msg string) string { + translationRequest := requestUrl + url.QueryEscape(msg) + response, err := http.Get(translationRequest) + if err != nil { + fmt.Printf("[error] http request failed: %s", err) + os.Exit(1) + } + body, err := io.ReadAll(response.Body) + if err != nil { + fmt.Printf("[error] failed to parse server response: %s", err) + } + return string(body) +} diff --git a/ddd-book/multi-stage/cmd/client/ui.go b/ddd-book/multi-stage/cmd/client/ui.go new file mode 100644 index 0000000..33bd4d3 --- /dev/null +++ b/ddd-book/multi-stage/cmd/client/ui.go @@ -0,0 +1,105 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/charmbracelet/bubbles/textinput" + "github.com/charmbracelet/bubbles/viewport" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +func start() error { + p := tea.NewProgram(initialModel(), tea.WithAltScreen()) + + _, err := p.Run() + return err +} + +type ( + errMsg error +) + +type model struct { + viewport viewport.Model + messages []string + textinput textinput.Model + exitHint lipgloss.Style + err error +} + +func initialModel() model { + ti := textinput.New() + ti.Placeholder = "Translate a message..." + ti.Focus() + + ti.CharLimit = 42 + + ti.Width = 42 + + vp := viewport.New(42, 2) + vp.SetContent(`Hit Enter to translate.`) + vp.Style = lipgloss.NewStyle(). + BorderStyle(lipgloss.RoundedBorder()). + BorderForeground(lipgloss.Color("69")). + Padding(0, 1). + MarginLeft(1) + + return model{ + textinput: ti, + messages: []string{}, + viewport: vp, + exitHint: lipgloss.NewStyle().Faint(true).MarginLeft(1), + err: nil, + } +} + +func (m model) Init() tea.Cmd { + return textinput.Blink +} + +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var ( + tiCmd tea.Cmd + vpCmd tea.Cmd + ) + + m.textinput, tiCmd = m.textinput.Update(msg) + m.viewport, vpCmd = m.viewport.Update(msg) + + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.Type { + case tea.KeyCtrlC, tea.KeyEsc: + fmt.Println(m.textinput.Value()) + return m, tea.Quit + case tea.KeyEnter: + translated := getTranslation(m.textinput.Value()) + + m.messages = append( + m.messages, + "Input: "+m.textinput.Value(), + "Translation: "+translated, + ) + m.viewport.SetContent(strings.Join(m.messages, "\n")) + m.textinput.Reset() + m.viewport.GotoBottom() + } + + // We handle errors just like any other message + case errMsg: + m.err = msg + return m, nil + } + + return m, tea.Batch(tiCmd, vpCmd) +} + +func (m model) View() string { + return fmt.Sprintf( + "\n%s\n%s\n", + m.textinput.View(), + m.viewport.View(), + ) + m.exitHint.Render("Ctrl+C to exit.") +} diff --git a/ddd-book/multi-stage/cmd/server/main.go b/ddd-book/multi-stage/cmd/server/main.go new file mode 100644 index 0000000..68898d9 --- /dev/null +++ b/ddd-book/multi-stage/cmd/server/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "log" + "net/http" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" +) + +// version is defined using build args +var version string + +func main() { + if version != "" { + log.Printf("Version: %s", version) + } + r := chi.NewRouter() + r.Use(middleware.Logger) + r.Get("/", func(w http.ResponseWriter, r *http.Request) { + msg := r.URL.Query().Get("s") + translated := translate(msg) + w.Write([]byte(translated)) + }) + + log.Println("Starting server...") + log.Println("Listening on HTTP port 3000") + log.Fatal(http.ListenAndServe(":3000", r)) +} diff --git a/ddd-book/multi-stage/cmd/server/translate.go b/ddd-book/multi-stage/cmd/server/translate.go new file mode 100644 index 0000000..bbcc5d3 --- /dev/null +++ b/ddd-book/multi-stage/cmd/server/translate.go @@ -0,0 +1,28 @@ +package main + +import ( + "strings" + "unicode" +) + +func translate(msg string) string { + msg = strings.ToLower(msg) + var b strings.Builder + for _, char := range msg { + if unicode.IsLetter(char) { + switch char { + case 'a', 'e', 'i', 'o', 'u', 'y', 'å', 'ä', 'ö': + b.WriteRune(char) + default: + b.WriteRune(char) + b.WriteRune('o') + b.WriteRune(char) + } + continue + } + if unicode.IsSpace(char) { + b.WriteRune(' ') + } + } + return b.String() +} diff --git a/ddd-book/multi-stage/go.mod b/ddd-book/multi-stage/go.mod new file mode 100644 index 0000000..cb9f503 --- /dev/null +++ b/ddd-book/multi-stage/go.mod @@ -0,0 +1,28 @@ +module github.com/dvdksn/buildme + +go 1.20 + +require ( + github.com/charmbracelet/bubbles v0.14.0 + github.com/charmbracelet/bubbletea v0.23.1 + github.com/charmbracelet/lipgloss v0.6.0 + github.com/go-chi/chi/v5 v5.0.0 +) + +require ( + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aymanbagabas/go-osc52 v1.0.3 // indirect + github.com/containerd/console v1.0.3 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/muesli/termenv v0.13.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect +) diff --git a/ddd-book/multi-stage/go.sum b/ddd-book/multi-stage/go.sum new file mode 100644 index 0000000..f1892a3 --- /dev/null +++ b/ddd-book/multi-stage/go.sum @@ -0,0 +1,60 @@ +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg= +github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= +github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og= +github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= +github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= +github.com/charmbracelet/bubbletea v0.23.1 h1:CYdteX1wCiCzKNUlwm25ZHBIc1GXlYFyUIte8WPvhck= +github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU= +github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= +github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= +github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= +github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg= +github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0= +github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/ddd-book/swarm-app/.DS_Store b/ddd-book/swarm-app/.DS_Store new file mode 100644 index 0000000..9a0a61f Binary files /dev/null and b/ddd-book/swarm-app/.DS_Store differ diff --git a/ddd-book/swarm-app/Dockerfile b/ddd-book/swarm-app/Dockerfile new file mode 100644 index 0000000..28a19c6 --- /dev/null +++ b/ddd-book/swarm-app/Dockerfile @@ -0,0 +1,16 @@ +# Base image +FROM python:alpine + +# Copy app, templates and views +COPY . /app + +# Set working directory for subsequent commands +WORKDIR /app + +# Install dependencies +RUN pip install -r requirements.txt + +EXPOSE 8080 + +# Command to run when container starts +ENTRYPOINT ["python", "app/app.py"] diff --git a/ddd-book/swarm-app/README.md b/ddd-book/swarm-app/README.md new file mode 100644 index 0000000..4b4673b --- /dev/null +++ b/ddd-book/swarm-app/README.md @@ -0,0 +1,21 @@ +# Simple counter-app for demonstrating Docker Compose +Flask app that counts page refreshes in Redis backend and displays the name of the container that services each request. + +**Used in:** +- Docker Deep Dive book 2023 edition + +**Pre-built image:** [](https://hub.docker.com/repository/docker/nigelpoulton/ddd-book/) **tag:** `swarm-app` + +### v2 app + +The `swarm-appv2` tag was built by making two changes to the app. + +Changing the image referenced in `index.html` from `image.png` to `wasm.ong` and changing the text. + +Changing the CSS to: + +``` +header { + background-color: #5a2d8c; +``` + diff --git a/ddd-book/swarm-app/app/.DS_Store b/ddd-book/swarm-app/app/.DS_Store new file mode 100644 index 0000000..7e66bfe Binary files /dev/null and b/ddd-book/swarm-app/app/.DS_Store differ diff --git a/ddd-book/swarm-app/app/app.py b/ddd-book/swarm-app/app/app.py new file mode 100644 index 0000000..1ea2928 --- /dev/null +++ b/ddd-book/swarm-app/app/app.py @@ -0,0 +1,27 @@ +import time +import redis +from flask import Flask, render_template +import socket + +app = Flask(__name__) +cache = redis.Redis(host='redis', port=6379) + +def get_hit_count(): + retries = 5 + while True: + try: + return cache.incr('hits') + except redis.exceptions.ConnectionError as exc: + if retries == 0: + raise exc + retries -= 1 + time.sleep(0.5) + +@app.route("/") +def index(): + count = get_hit_count() + hostname = socket.gethostname() + return render_template('index.html', hostname=hostname, count=count) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=8080, debug=True) diff --git a/ddd-book/swarm-app/app/static/.DS_Store b/ddd-book/swarm-app/app/static/.DS_Store new file mode 100644 index 0000000..1d2574a Binary files /dev/null and b/ddd-book/swarm-app/app/static/.DS_Store differ diff --git a/ddd-book/swarm-app/app/static/css/.DS_Store b/ddd-book/swarm-app/app/static/css/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/ddd-book/swarm-app/app/static/css/.DS_Store differ diff --git a/ddd-book/swarm-app/app/static/css/main.css b/ddd-book/swarm-app/app/static/css/main.css new file mode 100644 index 0000000..7fd8bc2 --- /dev/null +++ b/ddd-book/swarm-app/app/static/css/main.css @@ -0,0 +1,81 @@ +body { + margin: 0; + padding: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #444; +} +/* + * Formatting the header area + */ +header { + background-color: #48c1f5; + height: 35px; + width: 100%; + opacity: .9; + margin-bottom: 10px; +} +header h1.logo { + margin: 0; + font-size: 1.7em; + color: #fff; + text-align: center; +} +header h1.logo:hover { + color: #fff; + text-decoration: none; +} +/* + * Centering the body content + */ +.container { + width: 1200px; + margin: 0 auto; +} +div.home { + padding: 10px 0 30px 0; + background-color: #E6E6FA; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +div.about { + padding: 10px 0 30px 0; + background-color: #E6E6FA; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +h2 { + font-size: 3em; + margin-top: 40px; + text-align: center; + letter-spacing: -2px; +} +h3 { + font-size: 1.7em; + font-weight: 100; + margin-top: 30px; + text-align: center; + letter-spacing: -1px; + color: #999; +} +.menu { + float: right; + margin-top: 8px; +} +.menu li { + display: inline; +} +.menu li + li { + margin-left: 35px; +} +.menu li a { + color: #444; + text-decoration: none; +} +.center { + display: block; + margin-left: auto; + margin-right: auto; + width: 50%; +} \ No newline at end of file diff --git a/ddd-book/swarm-app/app/static/images/.DS_Store b/ddd-book/swarm-app/app/static/images/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/ddd-book/swarm-app/app/static/images/.DS_Store differ diff --git a/ddd-book/swarm-app/app/static/images/bkp image.png b/ddd-book/swarm-app/app/static/images/bkp image.png new file mode 100644 index 0000000..3c4113f Binary files /dev/null and b/ddd-book/swarm-app/app/static/images/bkp image.png differ diff --git a/ddd-book/swarm-app/app/static/images/image.png b/ddd-book/swarm-app/app/static/images/image.png new file mode 100644 index 0000000..9a39855 Binary files /dev/null and b/ddd-book/swarm-app/app/static/images/image.png differ diff --git a/ddd-book/swarm-app/app/templates/error.html b/ddd-book/swarm-app/app/templates/error.html new file mode 100644 index 0000000..1d7761b --- /dev/null +++ b/ddd-book/swarm-app/app/templates/error.html @@ -0,0 +1,10 @@ + + + + + Error page + + + Throwing an error + + diff --git a/ddd-book/swarm-app/app/templates/index.html b/ddd-book/swarm-app/app/templates/index.html new file mode 100644 index 0000000..33b7186 --- /dev/null +++ b/ddd-book/swarm-app/app/templates/index.html @@ -0,0 +1,20 @@ + + + + + Docker FTW + + + + NP logo +
+
+

Docker FTW

+
+
+
+

Request served by {{ hostname }}

+

You've refreshed {{ count }} times

+
+ + \ No newline at end of file diff --git a/ddd-book/swarm-app/compose.yaml b/ddd-book/swarm-app/compose.yaml new file mode 100644 index 0000000..09d6ec6 --- /dev/null +++ b/ddd-book/swarm-app/compose.yaml @@ -0,0 +1,42 @@ +# Un-comment the version field if you get an 'unsupported Compose file version: 1.0' ERROR + +#version: '3.8' +networks: + counter-net: + driver: overlay + driver_opts: + encrypted: 'yes' +volumes: + counter-vol: + +services: + web-fe: + image: nigelpoulton/ddd-book:swarm-app + command: python app.py + deploy: + replicas: 4 + update_config: + parallelism: 2 + delay: 10s + failure_action: rollback + placement: + constraints: + - 'node.role == worker' + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + networks: + - counter-net + ports: + - published: 5001 + target: 8080 + volumes: + - type: volume + source: counter-vol + target: /app + redis: + image: "redis:alpine" + networks: + counter-net: diff --git a/ddd-book/swarm-app/requirements.txt b/ddd-book/swarm-app/requirements.txt new file mode 100644 index 0000000..770a967 --- /dev/null +++ b/ddd-book/swarm-app/requirements.txt @@ -0,0 +1,3 @@ +flask +redis +jinja2 \ No newline at end of file diff --git a/ddd-book/web-app-0.2/.DS_Store b/ddd-book/web-app-0.2/.DS_Store new file mode 100644 index 0000000..f28aa74 Binary files /dev/null and b/ddd-book/web-app-0.2/.DS_Store differ diff --git a/ddd-book/web-app-0.2/Dockerfile b/ddd-book/web-app-0.2/Dockerfile new file mode 100644 index 0000000..470c592 --- /dev/null +++ b/ddd-book/web-app-0.2/Dockerfile @@ -0,0 +1,19 @@ +# Test web-app to use with Pluralsight courses and Docker Deep Dive book +FROM alpine + +LABEL maintainer="nigelpoulton@hotmail.com" + +# Install Node and NPM +RUN apk add --update nodejs npm curl + +# Copy app to /src +COPY . /src + +WORKDIR /src + +# Install dependencies +RUN npm install + +EXPOSE 8080 + +ENTRYPOINT ["node", "./app.js"] diff --git a/ddd-book/web-app-0.2/README.md b/ddd-book/web-app-0.2/README.md new file mode 100644 index 0000000..01acf49 --- /dev/null +++ b/ddd-book/web-app-0.2/README.md @@ -0,0 +1,15 @@ +# Readme + +Used to build the `web0.2` tag with three books listed instead of 2. + +Exposes web server on port `8080` as per `./app.js` + +See `Dockerfile` for more details + +Referenced in: +- [Docker Deep Dive book][1] + +**The app is maintained approximately once per year so may contain vulnerbilities.** + + +[1]: https://www.amazon.com/Docker-Deep-Dive-Nigel-Poulton/dp/1521822808/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr= \ No newline at end of file diff --git a/ddd-book/web-app-0.2/app.js b/ddd-book/web-app-0.2/app.js new file mode 100644 index 0000000..cb5b4e8 --- /dev/null +++ b/ddd-book/web-app-0.2/app.js @@ -0,0 +1,17 @@ +// Sample node.js web app for Pluralsight Docker CI course +// For demonstration purposes only +'use strict'; + +var express = require('express'), + app = express(); + +app.set('views', 'views'); +app.set('view engine', 'pug'); + +app.get('/', function(req, res) { + res.render('home', { + }); +}); + +app.listen(8080); +module.exports.getApp = app; diff --git a/ddd-book/web-app-0.2/package.json b/ddd-book/web-app-0.2/package.json new file mode 100644 index 0000000..b2ff584 --- /dev/null +++ b/ddd-book/web-app-0.2/package.json @@ -0,0 +1,15 @@ +{ + "name": "container-web-test", + "private": true, + "version": "0.0.5", + "description": "Demo app for web container demonstrations", + "main": "app.js", + "author": "Nigel Poulton (https://nigelpoulton.com)", + "license": "May contain vulnerabilities!", + "dependencies": { + "express": "4.18.2", + "pug": "3.0.2", + "mocha": "10.2.0", + "supertest": "6.3.3" + } +} diff --git a/ddd-book/web-app-0.2/views/home.pug b/ddd-book/web-app-0.2/views/home.pug new file mode 100644 index 0000000..877f86a --- /dev/null +++ b/ddd-book/web-app-0.2/views/home.pug @@ -0,0 +1,18 @@ +html + head + title='Docker FTW' + link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css') + body + div.container + div.jumbotron + h1 Hello Docker learners!!! + h2 New book: The KCNA Book + p + a.btn.btn-primary(href="https://www.amazon.com/Quick-Start-Kubernetes-Nigel-Poulton-ebook/dp/B08T21NW4Z/ref=sr_1_1?dchild=1&keywords=quick+start+kubernetes&qid=1625132469&sr=8-1" target="_blank") Quick Start Kubernetes + + a.btn.btn-outline-primary(href="https://www.amazon.com/Kubernetes-Book-Version-November-2018-ebook/dp/B072TS9ZQZ/ref=sr_1_1?dchild=1&keywords=the+kubernetes+book&qid=1625132902&sr=8-1" target="_blank") The Kubernetes Book + + a.btn.btn-primary(href="https://www.amazon.com/KCNA-Book-Kubernetes-Native-Associate/dp/1916585035/ref=sr_1_1?crid=2DWVNBALQCOZD&keywords=kcna+book&qid=1684705492&sprefix=kcna+bo%2Caps%2C336&sr=8-1" target="_blank") The KCNA Book + + p + p Be careful. The last time I updated the packages in this app was May 2023. \ No newline at end of file diff --git a/ddd-book/web-app/.DS_Store b/ddd-book/web-app/.DS_Store new file mode 100644 index 0000000..ff3c3e3 Binary files /dev/null and b/ddd-book/web-app/.DS_Store differ diff --git a/ddd-book/web-app/Dockerfile b/ddd-book/web-app/Dockerfile new file mode 100644 index 0000000..470c592 --- /dev/null +++ b/ddd-book/web-app/Dockerfile @@ -0,0 +1,19 @@ +# Test web-app to use with Pluralsight courses and Docker Deep Dive book +FROM alpine + +LABEL maintainer="nigelpoulton@hotmail.com" + +# Install Node and NPM +RUN apk add --update nodejs npm curl + +# Copy app to /src +COPY . /src + +WORKDIR /src + +# Install dependencies +RUN npm install + +EXPOSE 8080 + +ENTRYPOINT ["node", "./app.js"] diff --git a/ddd-book/web-app/README.md b/ddd-book/web-app/README.md new file mode 100644 index 0000000..6533b8b --- /dev/null +++ b/ddd-book/web-app/README.md @@ -0,0 +1,13 @@ +# Simple web app for Docker Deep Dive book + +Exposes web server on port `8080` as per `./app.js` + +See `Dockerfile` for more details + +Referenced in: +- [Docker Deep Dive][1] + +**The app is maintained approximately once per year so may contain vulnerbilities.** + + +[1]: https://www.amazon.com/Docker-Deep-Dive-Nigel-Poulton/dp/1521822808/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr= \ No newline at end of file diff --git a/ddd-book/web-app/app.js b/ddd-book/web-app/app.js new file mode 100644 index 0000000..cb5b4e8 --- /dev/null +++ b/ddd-book/web-app/app.js @@ -0,0 +1,17 @@ +// Sample node.js web app for Pluralsight Docker CI course +// For demonstration purposes only +'use strict'; + +var express = require('express'), + app = express(); + +app.set('views', 'views'); +app.set('view engine', 'pug'); + +app.get('/', function(req, res) { + res.render('home', { + }); +}); + +app.listen(8080); +module.exports.getApp = app; diff --git a/ddd-book/web-app/package.json b/ddd-book/web-app/package.json new file mode 100644 index 0000000..b2ff584 --- /dev/null +++ b/ddd-book/web-app/package.json @@ -0,0 +1,15 @@ +{ + "name": "container-web-test", + "private": true, + "version": "0.0.5", + "description": "Demo app for web container demonstrations", + "main": "app.js", + "author": "Nigel Poulton (https://nigelpoulton.com)", + "license": "May contain vulnerabilities!", + "dependencies": { + "express": "4.18.2", + "pug": "3.0.2", + "mocha": "10.2.0", + "supertest": "6.3.3" + } +} diff --git a/ddd-book/web-app/views/home.pug b/ddd-book/web-app/views/home.pug new file mode 100644 index 0000000..96ce3b2 --- /dev/null +++ b/ddd-book/web-app/views/home.pug @@ -0,0 +1,17 @@ +html + head + title='Docker FTW' + link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css') + body + div.container + div.jumbotron + h1 Hello Docker learners!!! + h2 Check out my other books + p + a.btn.btn-primary(href="https://www.amazon.com/Quick-Start-Kubernetes-Nigel-Poulton-ebook/dp/B08T21NW4Z/ref=sr_1_1?dchild=1&keywords=quick+start+kubernetes&qid=1625132469&sr=8-1" target="_blank") Quick Start Kubernetes + + a.btn.btn-outline-primary(href="https://www.amazon.com/Kubernetes-Book-Version-November-2018-ebook/dp/B072TS9ZQZ/ref=sr_1_1?dchild=1&keywords=the+kubernetes+book&qid=1625132902&sr=8-1" target="_blank") The Kubernetes Book + + p + p Be careful. The last time I updated the packages in this app was May 2023. + diff --git a/useful_commands.md b/useful_commands.md new file mode 100644 index 0000000..f278c7a --- /dev/null +++ b/useful_commands.md @@ -0,0 +1,36 @@ +# Get containers list +``` +docker ps -a +``` + +# Remove container by ID +``` +docker rm <> +``` + +# Run container with name +``` +docker run --name some_name -ti ubuntu:latest /bin/bash +``` + +# Stop container +``` +docker stop <> +``` + +# Inspect docker container stats +``` +docker inspect <> +``` + +# Set restart policy to conatiner +``` +docker run -d --restart (always|unless-stoppe|on-failure) +``` + +# Run container detached +``` +docker run -d ... +``` +`-d` flag instructs the container to run in detached mode + diff --git a/web_server/notes.md b/web_server/notes.md new file mode 100644 index 0000000..e69de29