Docker deep dive book materials

This commit is contained in:
pro100ton 2024-11-02 15:32:43 +03:00
commit e6b9c0f652
56 changed files with 969 additions and 0 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "ddd-book"]
path = ddd-book
url = https://github.com/nigelpoulton/ddd-book.git

7
ddd-book/README.md Normal file
View file

@ -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 ``

BIN
ddd-book/multi-contianer/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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"]

View file

@ -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`

BIN
ddd-book/multi-contianer/app/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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)

Binary file not shown.

Binary file not shown.

View file

@ -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%;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error page</title>
</head>
<body>
Throwing an error
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Suck my pipa</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
<body>
<img src="/static/images/image.png" alt="NP logo" class="center">
<header>
<div class="container">
<h1 class="logo">Suck my pipa</h1>
</div>
</header>
<div class="container">
<h2>Hit refresh if you think Sunderland AFC are the greatest football team in the world ;-)</h2>
<h3>You've refreshed bibas <b>{{ count }}</b> times</h3>
</div>
</body>
</html>

View file

@ -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:

View file

@ -0,0 +1,3 @@
flask
redis
jinja2

BIN
ddd-book/multi-stage/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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" ]

View file

@ -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" ]

View file

@ -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.

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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.")
}

View file

@ -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))
}

View file

@ -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()
}

View file

@ -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
)

View file

@ -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=

BIN
ddd-book/swarm-app/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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"]

View file

@ -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;
```

BIN
ddd-book/swarm-app/app/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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)

BIN
ddd-book/swarm-app/app/static/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

View file

@ -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%;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error page</title>
</head>
<body>
Throwing an error
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Docker FTW</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
<body>
<img src="/static/images/image.png" alt="NP logo" class="center">
<header>
<div class="container">
<h1 class="logo">Docker FTW</h1>
</div>
</header>
<div class="container">
<h2>Request served by <b>{{ hostname }}</b></h2>
<h3>You've refreshed <b>{{ count }}</b> times</h3>
</div>
</body>
</html>

View file

@ -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:

View file

@ -0,0 +1,3 @@
flask
redis
jinja2

BIN
ddd-book/web-app-0.2/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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"]

View file

@ -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=

View file

@ -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;

View file

@ -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 <nigelpoulton@hotmail.com> (https://nigelpoulton.com)",
"license": "May contain vulnerabilities!",
"dependencies": {
"express": "4.18.2",
"pug": "3.0.2",
"mocha": "10.2.0",
"supertest": "6.3.3"
}
}

View file

@ -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.

BIN
ddd-book/web-app/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -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"]

View file

@ -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=

17
ddd-book/web-app/app.js Normal file
View file

@ -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;

View file

@ -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 <nigelpoulton@hotmail.com> (https://nigelpoulton.com)",
"license": "May contain vulnerabilities!",
"dependencies": {
"express": "4.18.2",
"pug": "3.0.2",
"mocha": "10.2.0",
"supertest": "6.3.3"
}
}

View file

@ -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.

36
useful_commands.md Normal file
View file

@ -0,0 +1,36 @@
# Get containers list
```
docker ps -a
```
# Remove container by ID
```
docker rm <<container_id>>
```
# Run container with name
```
docker run --name some_name -ti ubuntu:latest /bin/bash
```
# Stop container
```
docker stop <<ID/name/...>>
```
# Inspect docker container stats
```
docker inspect <<ID/name/...>>
```
# 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

0
web_server/notes.md Normal file
View file