Docker Archives - Justin Silver https://www.justinsilver.com/tag/docker/ Technology, Travel, and Pictures Mon, 16 Sep 2024 16:33:58 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.1 https://www.justinsilver.com/wp-content/uploads/2013/06/cropped-apple-touch-icon-160x160.png Docker Archives - Justin Silver https://www.justinsilver.com/tag/docker/ 32 32 NGINX Feature Flag Reverse Proxy https://www.justinsilver.com/technology/nginx-feature-flag-reverse-proxy/?utm_source=rss&utm_medium=rss&utm_campaign=nginx-feature-flag-reverse-proxy https://www.justinsilver.com/technology/nginx-feature-flag-reverse-proxy/#respond Mon, 17 Jun 2024 20:23:48 +0000 https://www.justinsilver.com/?p=5402 Use NGINX as a reverse proxy to different back-end servers based on feature-flags set in the ngx_http_auth_request_module add-on. In my implementation for Secret Party the subdomain is used to determine which event/party a Note...

The post NGINX Feature Flag Reverse Proxy appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

Use NGINX as a reverse proxy to different back-end servers based on feature-flags set in the ngx_http_auth_request_module add-on. In my implementation for Secret Party the subdomain is used to determine which event/party a Note that this is a template file and some variables are set from the environment – $DOMAIN, $PROXY_*_HOST, $PROXY_*_PORT, etc.

Upstream Servers

First create the upstream servers that we can proxy the request to. Here we will use “green”, “blue”, and “red”.

# this is the server that handles the "auth" request
upstream upstream_auth {
  server $PROXY_AUTH_HOST:$PROXY_AUTH_PORT;
}

# backend app server "green"
upstream upstream_green {
  server $PROXY_GREEN_HOST:$PROXY_GREEN_PORT;
}

# backend app server "blue"
upstream upstream_blue {
  server $PROXY_BLUE_HOST:$PROXY_BLUE_PORT;
}

# backend app server "red"
upstream upstream_red {
  server $PROXY_RED_HOST:$PROXY_RED_PORT;
}

Mappings

Next we create a mapping of route name to upstream server. This will let us choose the backend/upstream server without an evil if.

# map service names from auth header to upstream service
map $wildcard_feature_route $wildcard_service_route {
  default upstream_green;
  'green' upstream_green;
  'blue' upstream_blue;
  'red' upstream_red;
}

Optionally we can also support arbitrary response codes in this mapping – note that they will be strings not numbers. This uses the auth response code to choose the route that is used for the proxy from the mapping above – so the HTTP Status Code to string to Upstream Server.

# map http codes from auth response (as string!) to upstream service
map $wildcard_backend_status $wildcard_mapped_route {
  default 'green';
  '480' 'green';
  '481' 'blue';
  '482' 'red';
}

Auth Handler

The Auth Handler is where NGINX sends the auth request so we assume we are handling something like http://upstream_auth/feature-flags/$host. This endpoint chooses the route that we use either by setting a header called X-Feature-Route with a string name that matches the mapping above, or can respond with a 4xx error code to also specify a route from the other mapping above. You get the gist.

function handleFeatureFlag(req, res) {
    // use the param/header data to choose the backend route
    // const hostname = req.params.hostname;
    const route = someFlag? 'green' : 'blue';
    // this header is used to figure out a proxy route
    res.header('X-Feature-Route', route);
    return res.status(200).send();
}
function handleFeatureFlag(req, res) {
    // this http response code can be used to figure out a proxy route too!
    const status = someFlag ? 481 : 482; // blue, red
    return res.status(status).send();
}

Server Configuration

To tie it together create a server that uses an auth request to http://upstream_auth/feature-flags/$host. This API endpoint uses the hostname to choose the upstream service to use to fulfill the request, either by setting a header of X-Feature-Route or returning an error code other than 200 or 401 – anything else will be returned as a 500 to NGINX which can then use the string value of this code as a route hint.

server {
  listen 80;

  # listen on wildcard subdomains
  server_name *.$DOMAIN;

  # internal feature flags route to upstream_auth
  location = /feature-flags {
    internal;
    # make an api request for the feature flags, pass the hostname
    rewrite .* /feature-flags/$host? break;
    proxy_pass http://upstream_auth;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
    proxy_set_header X-Original-Remote-Addr $remote_addr;
    proxy_set_header X-Original-Host $host;
  }

  # handle all requests for the wildcard
  location / {
    # get routing from feature flags
    auth_request /feature-flags;
    # set Status Code response to variable
    auth_request_set $wildcard_backend_status $upstream_status;
    # set X-Feature-Route header to variable
    auth_request_set $wildcard_feature_route $upstream_http_x_feature_route;

    # this is a 401 response
    error_page 401 = @process_backend;

    # anything not a 200 or 401 returns a 500 error
    error_page 500 = @process_backend;

    # this is a 200 response
    try_files @ @process_request;
  }

  # handle 500 errors to get the underlying code
  location @process_backend {
    # set the status code as a string mapped to a service name
    set $wildcard_feature_route $wildcard_mapped_route;

    # now process the request as normal
    try_files @ @process_request;
  }

  # send the request to the correct backend server
  location @process_request {
    proxy_read_timeout 10s;
    proxy_cache off;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # use the mapping to determine which service to route the request to
    proxy_pass http://$wildcard_service_route;
  }
}

The post NGINX Feature Flag Reverse Proxy appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/nginx-feature-flag-reverse-proxy/feed/ 0
Fantom Lachesis Full Node RPC https://www.justinsilver.com/technology/blockchain/fantom-lachesis-full-node-rpc/?utm_source=rss&utm_medium=rss&utm_campaign=fantom-lachesis-full-node-rpc https://www.justinsilver.com/technology/blockchain/fantom-lachesis-full-node-rpc/#respond Fri, 30 Apr 2021 00:16:05 +0000 https://www.justinsilver.com/?p=4997 Create an Alpine Linux image to run the lachesis node for the Fantom cryptocurrency. The run.sh just starts the nodes with the ports you set in the environment. Use docker-compose to define the TCP/UDP...

The post Fantom Lachesis Full Node RPC appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

Create an Alpine Linux image to run the lachesis node for the Fantom cryptocurrency.

FROM alpine:latest as build-stage

ARG LACHESIS_VERSION=release/1.0.0-rc.0

ENV GOROOT=/usr/lib/go 
ENV GOPATH=/go 
ENV PATH=$GOROOT/bin:$GOPATH/bin:/build:$PATH

RUN set -xe; \
  apk add --no-cache --virtual .build-deps \
  # get the build dependencies for go
  git make musl-dev go linux-headers; \
  # install fantom lachesis from github
  mkdir -p ${GOPATH}; cd ${GOPATH}; \
  git clone --single-branch --branch ${LACHESIS_VERSION} https://github.com/Fantom-foundation/go-lachesis.git; \
  cd go-lachesis; \
  make build -j$(nproc); \
  mv build/lachesis /usr/local/bin; \
  rm -rf /go; \
  # remove our build dependencies
  apk del .build-deps; 

FROM alpine:latest as lachesis

# copy the binary 
COPY --from=build-stage /usr/local/bin/lachesis /usr/local/bin/lachesis

COPY run.sh /usr/local/bin

WORKDIR /root

ENV LACHESIS_PORT=5050
ENV LACHESIS_HTTP=18545
ENV LACHESIS_API=eth,ftm,debug,admin,web3,personal,net,txpool
ENV LACHESIS_VERBOSITY=2

EXPOSE ${LACHESIS_PORT}
EXPOSE ${LACHESIS_HTTP}

VOLUME [ "/root/.lachesis" ]

CMD ["run.sh"]

The run.sh just starts the nodes with the ports you set in the environment.

#!/usr/bin/env sh

set -xe

lachesis \
  --port ${LACHESIS_PORT} \
  --http \
  --http.addr "0.0.0.0" \
  --http.port ${LACHESIS_HTTP} \
  --http.api "${LACHESIS_API}" \
  --nousb \
  --verbosity ${LACHESIS_VERBOSITY}

Use docker-compose to define the TCP/UDP ports to expose as well as a data volume to persist the blockchain data.

version: '3.4'

services:
  lachesis:
    image: doublesharp/fantom-lachesis:latest
    restart: always
    ports:
      - '5050:5050'
      - '5050:5050/udp'
      - '18545:18545'
    volumes:
      - lachesis:/root/.lachesis
    environment:
      LACHESIS_VERBOSITY: 2

volumes:
  lachesis: {}

The post Fantom Lachesis Full Node RPC appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/blockchain/fantom-lachesis-full-node-rpc/feed/ 0
Using APK for Alpine Linux with Docker https://www.justinsilver.com/technology/linux/using-apk-for-alpine-linux-with-docker/?utm_source=rss&utm_medium=rss&utm_campaign=using-apk-for-alpine-linux-with-docker https://www.justinsilver.com/technology/linux/using-apk-for-alpine-linux-with-docker/#respond Mon, 02 Dec 2019 23:41:36 +0000 https://www.justinsilver.com/?p=4902 Some quick tips on how to use apk for Alpine Linux in a Docker environment. Some common use cases might be to install command line tools you will use in scripts, or to compile...

The post Using APK for Alpine Linux with Docker appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

Some quick tips on how to use apk for Alpine Linux in a Docker environment. Some common use cases might be to install command line tools you will use in scripts, or to compile a PHP extension. In the former you will often be able to access a binary, and not need to worry about polluting much of your Docker layer with extra files. When you need to compile something however – like a PHP extension – you may need several build tools as well as libraries that you don’t need to keep around after you compile the module.

This first example is common for installing command line tools:

RUN apk add --no-cache --update \
  bash curl findutils sed sudo

The next example shows how to compile PHP modules and remove their dependencies after compilation.

RUN set -xe; \
    apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \
      # build tools
      autoconf g++ gcc make \
      # lib tools
      bzip2-dev freetype-dev gettext-dev icu-dev imagemagick-dev libintl libjpeg-turbo-dev \
      #  libmcrypt-dev 
      libpng-dev libxslt-dev libzip-dev \
      ; \
    docker-php-ext-configure \
      gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ \
      ; \
    docker-php-ext-install -j$(nproc) \
      bcmath bz2 calendar exif gettext gd intl mysqli opcache pcntl pdo_mysql soap xsl zip \
      ; \
    pecl channel-update pecl.php.net && \
    pecl install -o -f \
      redis \
      ; \
    docker-php-ext-enable \
      redis \
      ; \
    runDeps="$( \
      scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
        | tr ',' '\n' \
        | sort -u \
        | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
    )"; \
      apk add --virtual .phpexts-rundeps $runDeps; \
      apk del .build-deps

The post Using APK for Alpine Linux with Docker appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/linux/using-apk-for-alpine-linux-with-docker/feed/ 0
Docker-CE on CentOS 7 https://www.justinsilver.com/technology/linux/docker-ce-on-centos-7/?utm_source=rss&utm_medium=rss&utm_campaign=docker-ce-on-centos-7 https://www.justinsilver.com/technology/linux/docker-ce-on-centos-7/#respond Thu, 28 Mar 2019 14:48:29 +0000 https://www.justinsilver.com/?p=4815 Install Docker-CE (not just “docker) to get the latest version on CentOS. yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum makecache fast yum install -y docker-ce chkconfig docker on service docker start...

The post Docker-CE on CentOS 7 appeared first on Justin Silver.

]]>
AmpedSense.OptimizeAdSpot('AP'); AmpedSense.OptimizeAdSpot('IL'); AmpedSense.OptimizeAdSpot('IR');

Install Docker-CE (not just “docker) to get the latest version on CentOS.

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum makecache fast
yum install -y docker-ce
chkconfig docker on
service docker start

Update firewalld to allow host/container traffic.

Restart firewalld to pick up the changes.

# trust the docker interface
firewall-cmd --permanent --zone=trusted --change-interface=docker0
# accept IPv4 traffic
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 4 -i docker0 -j ACCEPT
# any ports on the host you want to access from the containers (strapi port 1337 here)
firewall-cmd --permanent --zone=trusted --add-port=1337/tcp
firewall-cmd --reload
service docker restart

Create a group named “docker” and add any users that are allowed to create containers.

groupadd docker
# allow users to access docker by adding them to the docker group
# usermod -aG docker $USER

Use an entrypoint file to create an entry in /etc/hosts to point to the host. Requires ping and ip on the machine, on Debian these are found in the apt packages inetutils-ping and iproute.

#!/bin/bash

# fix for linux hosts
HOST_DOMAIN="host.docker.internal"
ping -q -c1 $HOST_DOMAIN > /dev/null 2>&1
if [ $? -ne 0 ]; then
  HOST_IP=$(ip route | awk 'NR==1 {print $3}')
  echo -e "$HOST_IP\t$HOST_DOMAIN" >> /etc/hosts
fi

exec "$@"

The post Docker-CE on CentOS 7 appeared first on Justin Silver.

]]>
https://www.justinsilver.com/technology/linux/docker-ce-on-centos-7/feed/ 0