print ('Name: ', Juan['name'])
print ('Email: ', Juan['email'])
print ('Work: ', Juan['work'])
Name: Juan A. Cabrera Email: juan.cabrera@tu-dresden.de Work: Deutsche Telekom Chair of Communication Networks
Slides: https://comnets.bitbucket.io/wcnc-tutorial/hands-on/
Press esc
for a menu of the slides
Slides inspired and adapted from:
Docker by Example, by:
Ganesh & Hari {ganesh|hari}(at)codeops.tech
%%bash
docker -v
Docker version 18.09.4-ce, build d14af54266
%%bash
docker info
Containers: 50 Running: 0 Paused: 0 Stopped: 50 Images: 46 Server Version: 18.09.4-ce Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: bb71b10fd8f58240ca47fbb579b9d1028eea7c84.m runc version: 69ae5da6afdcaaf38285a10b36f362e41cb298d6 init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 4.9.166-1-MANJARO Operating System: Manjaro Linux OSType: linux Architecture: x86_64 CPUs: 4 Total Memory: 7.513GiB Name: theshire ID: E633:V5GR:2JQJ:6LP4:5LEV:P4D3:PSJK:3VTS:AOQQ:6ETU:LA47:2MNF Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false
%%bash
docker run docker/whalesay cowsay Hello World
_____________ < Hello World > ------------- \ \ \ ## . ## ## ## == ## ## ## ## === /""""""""""""""""___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\______/
%%bash
docker run hello-world
Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://cloud.docker.com/ For more examples and ideas, visit: https://docs.docker.com/engine/userguide/
%%bash
docker -h
Flag shorthand -h has been deprecated, please use --help Usage: docker [OPTIONS] COMMAND A self-sufficient runtime for containers Options: --config string Location of client config files (default "/home/juarch/.docker") -D, --debug Enable debug mode -H, --host list Daemon socket(s) to connect to -l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info") --tls Use TLS; implied by --tlsverify --tlscacert string Trust certs signed only by this CA (default "/home/juarch/.docker/ca.pem") --tlscert string Path to TLS certificate file (default "/home/juarch/.docker/cert.pem") --tlskey string Path to TLS key file (default "/home/juarch/.docker/key.pem") --tlsverify Use TLS and verify the remote -v, --version Print version information and quit Management Commands: builder Manage builds config Manage Docker configs container Manage containers engine Manage the docker engine image Manage images network Manage networks node Manage Swarm nodes plugin Manage plugins secret Manage Docker secrets service Manage services stack Manage Docker stacks swarm Manage Swarm system Manage Docker trust Manage trust on Docker images volume Manage volumes Commands: attach Attach local standard input, output, and error streams to a running container build Build an image from a Dockerfile commit Create a new image from a container's changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes to files or directories on a container's filesystem events Get real time events from the server exec Run a command in a running container export Export a container's filesystem as a tar archive history Show the history of an image images List images import Import the contents from a tarball to create a filesystem image info Display system-wide information inspect Return low-level information on Docker objects kill Kill one or more running containers load Load an image from a tar archive or STDIN login Log in to a Docker registry logout Log out from a Docker registry logs Fetch the logs of a container pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container ps List containers pull Pull an image or a repository from a registry push Push an image or a repository to a registry rename Rename a container restart Restart one or more containers rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save one or more images to a tar archive (streamed to STDOUT by default) search Search the Docker Hub for images start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers version Show the Docker version information wait Block until one or more containers stop, then print their exit codes Run 'docker COMMAND --help' for more information on a command.
%%bash
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE juancabre/verona latest 68b867c8e91b 4 months ago 170MB juancabre/test-pre-verona pingVim 947e9f61365b 4 months ago 226MB my-bench latest 196c732622cd 16 months ago 166MB my_server latest 187253ea98a9 16 months ago 108MB juancabre/ubu_lecture_dockerfile vim_config 08a2460bcd29 16 months ago 219MB juancabre/ubu_lecture latest e5dbcde14e04 16 months ago 224MB juancabre/ubu_lecture ping 0c285dd24f81 16 months ago 167MB nginx latest 40960efd7b8f 17 months ago 108MB haproxy latest f8177ad6f329 17 months ago 136MB mysql 5.7 5709795eeffa 17 months ago 408MB ubuntu <none> dd6f76d9cc90 17 months ago 122MB debian wheezy f47fe1c60a2f 17 months ago 85.1MB debian latest 6d83de432e98 17 months ago 100MB hello-world latest 725dcfab7d63 17 months ago 1.84kB alpine latest 053cde6e8953 17 months ago 3.97MB gcc 4.9 1b3de68a7ff8 19 months ago 1.37GB google/cadvisor latest f9ba08bafdea 2 years ago 57.3MB docker/whalesay latest 6b362a9f73eb 3 years ago 247MB
%%bash
docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating sys… 9380 [OK] dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 288 [OK] rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 211 [OK] consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 169 [OK] ubuntu-upstart Upstart is an event-based replacement for th… 97 [OK] ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 96 [OK] neurodebian NeuroDebian provides neuroscience research s… 56 [OK] 1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK] ubuntu-debootstrap debootstrap --variant=minbase --components=m… 40 [OK] nuagebec/ubuntu Simple always updated Ubuntu docker images w… 23 [OK] tutum/ubuntu Simple Ubuntu docker images with SSH access 20 i386/ubuntu Ubuntu is a Debian-based Linux operating sys… 17 1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0 13 [OK] ppc64le/ubuntu Ubuntu is a Debian-based Linux operating sys… 12 eclipse/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, … 8 [OK] codenvy/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc, … 5 [OK] darksheer/ubuntu Base Ubuntu Image -- Updated hourly 5 [OK] pivotaldata/ubuntu A quick freshening-up of the base Ubuntu doc… 2 smartentry/ubuntu ubuntu with smartentry 1 [OK] 1and1internet/ubuntu-16-sshd ubuntu-16-sshd 1 [OK] paasmule/bosh-tools-ubuntu Ubuntu based bosh-cli 1 [OK] pivotaldata/ubuntu-gpdb-dev Ubuntu images for GPDB development 0 ossobv/ubuntu Custom ubuntu image from scratch (based on o… 0 1and1internet/ubuntu-16-healthcheck ubuntu-16-healthcheck 0 [OK] 1and1internet/ubuntu-16-rspec ubuntu-16-rspec 0 [OK]
%%bash
docker pull ubuntu
Using default tag: latest latest: Pulling from library/ubuntu 898c46f3b1a1: Pulling fs layer 63366dfa0a50: Pulling fs layer 041d4cd74a92: Pulling fs layer 6e1bee0f8701: Pulling fs layer 6e1bee0f8701: Waiting 041d4cd74a92: Download complete 63366dfa0a50: Verifying Checksum 63366dfa0a50: Download complete 898c46f3b1a1: Verifying Checksum 898c46f3b1a1: Download complete 6e1bee0f8701: Verifying Checksum 6e1bee0f8701: Download complete 898c46f3b1a1: Pull complete 63366dfa0a50: Pull complete 041d4cd74a92: Pull complete 6e1bee0f8701: Pull complete Digest: sha256:017eef0b616011647b269b5c65826e2e2ebddbe5d1f8c1e56b3599fb14fabec8 Status: Downloaded newer image for ubuntu:latest
%%bash
docker pull alpine
Using default tag: latest latest: Pulling from library/alpine 8e402f1a9c57: Pulling fs layer 8e402f1a9c57: Verifying Checksum 8e402f1a9c57: Download complete 8e402f1a9c57: Pull complete Digest: sha256:644fcb1a676b5165371437feaa922943aaf7afcfa8bfee4472f6860aad1ef2a0 Status: Downloaded newer image for alpine:latest
from IPython.core.display import HTML
HTML('<a href="https://hub.docker.com/">Docker Hub</a>')
Alpine linux might be enough compared to Ubuntu image
%%bash
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE dock0/arch latest 9fd5c23f509f About an hour ago 575.5 MB nginx latest e43d811ce2f4 39 hours ago 181.4 MB dock0/arch <none> 9b9558aeec5c 4 days ago 573.6 MB alpine latest baa5d63471ea 4 days ago 4.799 MB nginx <none> a5311a310510 10 days ago 181.4 MB datadog/docker-dd-agent latest f385e05e1883 6 weeks ago 301.8 MB node 5-slim c7a1798865e7 7 weeks ago 207.5 MB ubuntu latest bd3d4369aebc 8 weeks ago 126.6 MB hello-world latest c54a2cc56cbb 3 months ago 1.848 kB gophernet/mz latest 71fa98ad2324 6 months ago 126.3 MB networkstatic/iperf3 latest 6ea158fee1a7 7 months ago 125.5 MB docker/whalesay latest 6b362a9f73eb 17 months ago 247 MB
%%bash
docker inspect alpine
[ { "Id": "sha256:5cb3aa00f89934411ffba5c063a9bc98ace875d8f92e77d0029543d9f2ef4ad0", "RepoTags": [ "alpine:latest" ], "RepoDigests": [ "alpine@sha256:644fcb1a676b5165371437feaa922943aaf7afcfa8bfee4472f6860aad1ef2a0" ], "Parent": "", "Comment": "", "Created": "2019-03-07T22:19:40.247110971Z", "Container": "277610461b47d66cbee3947628daa460aa62836414a2762aee57da387724e33e", "ContainerConfig": { "Hostname": "277610461b47", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/sh\"]" ], "ArgsEscaped": true, "Image": "sha256:0b7fc56164419dfc0ce9fd320acfc2032a72c3b7f276c5f04cb733f9a4f45c7f", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "DockerVersion": "18.06.1-ce", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh" ], "ArgsEscaped": true, "Image": "sha256:0b7fc56164419dfc0ce9fd320acfc2032a72c3b7f276c5f04cb733f9a4f45c7f", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 5529047, "VirtualSize": 5529047, "GraphDriver": { "Data": { "MergedDir": "/var/lib/docker/overlay2/1171039d01d98be6610528a4f999c2d7c3e0ab8e963913159372eb0acd042b2c/merged", "UpperDir": "/var/lib/docker/overlay2/1171039d01d98be6610528a4f999c2d7c3e0ab8e963913159372eb0acd042b2c/diff", "WorkDir": "/var/lib/docker/overlay2/1171039d01d98be6610528a4f999c2d7c3e0ab8e963913159372eb0acd042b2c/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:bcf2f368fe234217249e00ad9d762d8f1a3156d60c442ed92079fa5b120634a1" ] }, "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z" } } ]
%%bash
docker history ubuntu
IMAGE CREATED CREATED BY SIZE COMMENT 94e814e2efa8 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 3 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 3 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 3 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 3 weeks ago /bin/sh -c #(nop) ADD file:1d7cb45c4e196a6a8… 88.9MB
docker rmi <image-tag>
We create a container using docker run
specifically:
docker run OPTIONS <<image-tag>> CMD ARGS
docker run alpine ping "8.8.8.8"
docker run -t -i ubuntu /bin/bash
-t Attach a pseudo-tty console
-i Stands for Interactive
docker run -d ubuntu /bin/sh -c "while true; do $(echo date); sleep 2 ; done"
-d stands for detach
docker logs <Container-Tag>
We can do it with one command, without pre-installs
from IPython.display import IFrame
IFrame('https://en.wikipedia.org/wiki/Comparison_of_web_server_software#Overview', width=700, height=350)
%%bash
docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 11193 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1577 [OK] richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 702 [OK] jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as p… 500 [OK] webdevops/php-nginx Nginx with PHP-FPM 123 [OK] zabbix/zabbix-web-nginx-mysql Zabbix frontend based on Nginx web-server wi… 94 [OK] bitnami/nginx Bitnami nginx Docker Image 65 [OK] linuxserver/nginx An Nginx container, brought to you by LinuxS… 58 1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK] zabbix/zabbix-web-nginx-pgsql Zabbix frontend based on Nginx with PostgreS… 30 [OK] tobi312/rpi-nginx NGINX on Raspberry Pi / ARM 25 [OK] nginx/nginx-ingress NGINX Ingress Controller for Kubernetes 17 nginxdemos/hello NGINX webserver that serves a simple page co… 13 [OK] schmunk42/nginx-redirect A very simple container to redirect HTTP tra… 13 [OK] blacklabelops/nginx Dockerized Nginx Reverse Proxy Server. 12 [OK] wodby/drupal-nginx Nginx for Drupal container image 12 [OK] centos/nginx-18-centos7 Platform for running nginx 1.8 or building n… 10 centos/nginx-112-centos7 Platform for running nginx 1.12 or building … 7 1science/nginx Nginx Docker images that include Consul Temp… 4 [OK] nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 4 mailu/nginx Mailu nginx frontend 3 [OK] travix/nginx NGinx reverse proxy 2 [OK] toccoag/openshift-nginx Nginx reverse proxy for Nice running on same… 1 [OK] wodby/nginx Generic nginx 0 [OK] ansibleplaybookbundle/nginx-apb An APB to deploy NGINX 0 [OK]
docker run -d -p 80:80 nginx
-d stands for detach
-p stands for port. We basically say: "Redirect every incomming TCP packet at port 80 of the host, to the port 80 of the container"
from IPython.display import IFrame
IFrame('http://localhost:80', width=700, height=350)
When we use the flag -p
we "publish a port, or range of ports to the host".
Format: hostPort:containerPort
For UDP ports: hostPort:containerPort/udp
First we need to find the container
docker ps
Then, we stop it
docker stop CONTAINER_ID
Let us also delete it
docker rm CONTAINER_ID
Check that the container is not there anymore. Go to localhost:80 in your browser. You should see an error
Note: Use incognito mode. Otherwise, the browser will display the cached site.
docker run -d -p 45700:80 nginx
Now, if go in your browser to localhost:4570
Lets crreate the html file that we will serve from our containerized http server
index.html
=================================
<h1> Welcome to PBL </h1>
<h2> Have Fun! </h2>
Dockerfiles are like a recipe. It is a set of instructions used to create a custom image
Dockerfile
=================================
# Base image
FROM nginx:latest
# The maintainer
MAINTAINER Juan
# The actual recipe
# ADD Will add the created file in the step above
ADD ./index.html /usr/share/nginx/html/index.html
EXPOSE 80
docker build -t my_server .
docker run -p 80:80 -d my_server
They can be used to make data persistent
# Make a folder to store the data
mkdir ~/testing_data
# Run a container
docker run -v ~/testing_data:/container_volumes ubuntu /bin/sh -c "echo peristent data > /container_volumes/data.txt"
# Check that your data is there
cat ~/testing_data/data.txt
Dockerfile
=======================
FROM gcc:4.9
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN gcc -o myapp main.c
CMD ["./myapp"]
main.c
=======================
#include <stdio.h>
main()
{
printf("Hello container world\n");
}
# Build the image
docker build . -t my-gcc-app
# Run a container
docker run -rm my-gcc-app
Let us use sysbench
The cpu is one of the most simple benchmarks in SysBench. In this mode each request consists in calculation of prime numbers up to a value specified by the −−cpu−max−primes option. All calculations are performed using 64−bit integers.
Each thread executes the requests concurrently until either the total number of requests or the total execution time exceed the limits specified with the common command line options.
Dockerfile
=======================
FROM ubuntu:latest
MAINTAINER Juan
RUN apt-get update \
&& apt-get install -y sysbench
CMD sysbench --test=cpu --cpu-max-prime=35000 --num-threads=4 run
build it and run it to test it
There are several options out there.
Let us use Google's cAdvisor https://github.com/google/cadvisor
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
docker run --cpuset-cpus="0,1" my-benchmark
Go to https://hub.docker.com/ and create an account
The ubuntu image does not have the "ping" functionality installed. Lets add it.
docker run -it ubuntu
apt update
apt install inetutils-ping
exit
docker commit -a '[COMMIT AUTHOR]' -m 'ping function' [CONTAINER ID] [USERNAME]/ubu_lecture:ping
sudo docker login
sudo docker push juancabre/ubu_lecture:ping
I will do it for vim
sudo rmi juancabre/ubu_lecture:ping
docker pull juancabre/ubu_lecture:ping
docker commit -a 'Juan' -m 'ping function' a122a23fd3bb juancabre/ubu_lecture
sudo docker push juancabre/ubu_lecture
Dockerfile
=============================================
# Base image
FROM ubuntu
# The maintainer
MAINTAINER Juan Cabrera
# The actual recipee
RUN apt update;\
apt install -y vim
# Adding files
ADD https://gist.githubusercontent.com/anonymous/c966c0757f62b451bffa/raw/a15e10aa38d146bf50ee6c9d7fd851ce5bb91aee/gistfile1.txt /root/.vimrc
# The default command to run
CMD /bin/bash
docker build -t juancabre/dockerfile:vim_config .
docker run -it juancabre/dockerfile:vim_config
To set a word press, we need a data base and a wordpress server
We can use docker compose to have one file to rule them all
yml
version: '2'
services:
db:
image: mysql:5.7
volumes:
- ./db_volume:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_PASSWORD: wordpress
Let us run it!
docker-compose up -d
Try it in your browser
Excercise inspired from: http://blog.hypriot.com/
Lets create a webserver that performs a "computationally intensive" task
Let us create a Hello-World Node.js web application based on Express.js
Make two new folders: load-balancing/
and load-balancing/src/
We need 2 files inside load-balancing/src/
. Namely index.js
and package.json
load-balancing/src/index.js
var express = require('express');
var os = require("os");
var app = express();
var hostname = os.hostname();
app.get('/', function (req, res) {
// A CPU Intensive task:
for (var i = 0; i < 1000000 ; i++) {
Math.pow(i,i);
}
// Respond the request:
res.send('<html><body>Hello from Node.js container '
+ hostname + '</body></html>');
});
app.listen(80);
console.log('Running on http://localhost');
load-balancing/src/package.json
{
"name": "node-hello-world",
"private": true,
"version": "0.0.1",
"description": "Node.js Hello world app on docker",
"author": "hypriot.com",
"dependencies": {
"express": "4.12.0"
}
}
Now let us make the Dockerfile of our application
load-balancing/Dockerfile
FROM node
ADD src/ /src
WORKDIR /src
RUN npm install
EXPOSE 80
CMD ["node", "index.js"]
Build and run a container
docker build . -t node-hello
docker run -p 45700:80 --name web -d node-hello
Try it in your browser
Lets benchmark it:
htop
ab -n 10000 -c 100 http://localhost:45700/
load-balancing/docker-compose.yml
yml
weba:
build: .
expose:
- 80
webb:
build: .
expose:
- 80
webc:
build: .
expose:
- 80
haproxy:
image: haproxy
volumes:
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- weba
- webb
- webc
ports:
- "80:80"
- "70:70"
expose:
- "80"
- "70"
Haproxy config file
load-balancing/haproxy/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 10000
timeout server 10000
listen stats
bind :70
stats enable
stats uri /
frontend balancer
bind 0.0.0.0:80
mode http
default_backend aj_backends
backend aj_backends
mode http
option forwardfor
# http-request set-header X-Forwarded-Port %[dst_port]
balance roundrobin
server weba weba:80 check
server webb webb:80 check
server webc webc:80 check
# option httpchk OPTIONS * HTTP/1.1\r\nHost:\ localhost
option httpchk GET /
http-check expect status 200
Let us run it!
docker-compose up -d
Try it in your browser!
Let us benchmark this one! :D