Developer Blog

Tipps und Tricks für Entwickler und IT-Interessierte

Docker

Docker | Cookbook

Useful apps

portainer.io: MAKING DOCKER MANAGEMENT EASY. Build and manage your Docker environments with ease today.

dive: About A tool for exploring each layer in a docker image

Useful commands

  • docker ps — Lists running containers.
    Some useful flags include: -a / -all for all containers (default shows just running) and —-quiet /-q to list just their ids (useful for when you want to get all the containers).
  • docker pull — Most of your images will be created on top of a base image from the Docker Hub registry. Docker Hub contains many pre-built images that you can pull and try without needing to define and configure your own. To download a particular image, or set of images (i.e., a repository), use docker pull.
  • docker build — Builds Docker images from a Dockerfile and a “context”.
    A build’s context is the set of files located in the specified PATH or URL. Use the -t flag to label the image, for example docker build -t my_container . with the . at the end signalling to build using the currently directory.
  • docker run — Run a docker container based on an image.
    You can follow this on with other commands, such as -it bash to then run bash from within the container. 
    Also see Top 10 options for docker run — a quick reference guide for the CLI command
    docker run my_image -it bash
  • docker logs —  Display the logs of a container.
    You must specify a container and can use flags, such as --follow to follow the output in the logs of using the program. 
    docker logs --follow my_container
  • docker volume ls — Lists the volumes,.
    Volumes are the preferred mechanism for persisting data generated by and used by Docker containers.
  • docker rm — Removes one or more containers.
    docker rm my_container
  • docker rmi — Removes one or more images. 
    docker rmi my_image
  • docker stop — Stops one or more containers.
    docker stop my_containerstops one container, while docker stop $(docker ps -a -q) stops all running containers. A more direct way is to use docker kill my_container, which does not attempt to shut down the process gracefully first.
  • Use them together, for example to clean up all your docker images and containers:
  • kill all running containers with docker kill $(docker ps -q)
  • delete all stopped containers with docker rm $(docker ps -a -q)
  • delete all images with docker rmi $(docker images -q)

Create new container

Start a new docker image with a given name

You can start a new container by using the run command and specify the desired image 

$ docker run -it --name playground ubuntu:17.10 /bin/bash
....
root@c106fbb48b20:/# exit

As a result, you are in the container at the bash command line

Reconnect to image
$ docker attach playground
Commit changes in container
$ docker start playground
$ docker attach playground
root@c106fbb48b20:/# echo 1.0 >VERSION
root@c106fbb48b20:/# exit
$ docker commit playground playground:1.0
$ docker tag playground:1.0 playground:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
playground 1.0 01703597322b Less than a second ago 94.6MB
playground latest 01703597322b Less than a second ago 94.6MB

Add tools and utilities

Python

$ apt-get update 
$ apt-get upgrade 
$ apt-get install python3 python3-pip

Java

$ apt-get install default-jre

Manage File Shares

File shares with Docker Desktop on Mac OS

Configuration is stored under

~/Library/Group Containers/group.com.docker/settings.json

Monitor Docker Logs

Logs with Docker Desktop on Mac OS

pred='process matches ".*(ocker|vpnkit).*" || (process in {"taskgated-helper", "launchservicesd", "kernel"} && eventMessage contains[c] "docker")'
/usr/bin/log stream --style syslog --level=debug --color=always --predicate "$pred"

Alternative you can run

/usr/bin/log show --style syslog --debug --info --last 1d --predicate "$pred" >/tmp/logs.txt

Add Timezone Konfiguration

ENV TZ 'Europe/Berlin'

RUN echo $TZ > /etc/timezone 
RUN    apt-get install -y tzdata \
    && rm /etc/localtime \
    && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && dpkg-reconfigure -f noninteractive tzdata \
    && apt-get clean

Install local apps in a docker container

Install Atom Editor

Start docker image

$ docker run -it --name docker-atom -v /Dockerfiles/HOME:/home -e DISPLAY=192.168.99.1:0 ubuntu /bin/bash

Install Atom

# apt-get update
# apt-get install curl
# curl -sL https://deb.nodesource.com/setup_7.x | bash -
# apt-get install nodejs
# node -v
v7.4.0
# apt-get -y install git
# apt-get -y install software-properties-common
# add-apt-repository -y ppa:webupd8team/atom
# apt-get update
# apt-get -y install atom
# apt-get install libxss1

Commit changes  and build a image

# docker commit -a "Docker Tutorial 1.0.0" -m ionic d378e8647af9 atom:1.0.0
# docker tag atom:1.0.0 atom:latest

Links and Resources

Docker quick reference guides

Docker in more depth

Working with networks

I’ve got a lot of inspiration from wsargent/docker-cheat-sheet.

Goal

We will setup to applications, each in his one container, running on the smae network, so they can communication together.

Setup

Starting with the default configuration, you will see 4 networks

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6742a11bff1e        bridge              bridge              local
3af0a1c9eaac        host                host                local
e60f68aad9d6        none                null                local

Create a bridged network for running two apps inside: web and database

$ docker network create -d bridge playground_bridge
c97a80b449d9b6b28ddffa0a7bd4a7938e0b8261773080ab33ae4b7ab08826b1
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6742a11bff1e        bridge              bridge              local
3af0a1c9eaac        host                host                local
e60f68aad9d6        none                null                local
c97a80b449d9        playground_bridge   bridge              local

Start the database application using the bridges network

$ docker run -d --net=playground_bridge --name playground_db training/postgres
88abb9d018c628ed1abe7da0466289846a8342a28b2cbef3305ea5313c46d647
$ docker inspect --format='{{json .NetworkSettings.Networks}}' playground_db| python -m json.tool
{
    "playground_bridge": {
        "Aliases": [
            "88abb9d018c6"
        ],
        "DriverOpts": null,
        "EndpointID": "9fdfe9baf5b159471a39601779ee451aa555a9a9be72be4472e56bd3fcfd1350",
        "Gateway": "172.18.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAMConfig": null,
        "IPAddress": "172.18.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "Links": null,
        "MacAddress": "02:42:ac:12:00:02",
        "NetworkID": "c97a80b449d9b6b28ddffa0a7bd4a7938e0b8261773080ab33ae4b7ab08826b1"
    }
}

Now, start the web application with the default network (not the playground_bridge used by the database)

$ docker run -d --name playground_web training/webapp python app.py
2f31761168d75d10c2f1bffc805fb8963a18529e17c2592c2b279afd9e364e7b

They cannot communication, because they are running in different networks:

$ docker exec -it playground_db ifconfig | grep inet
         inet addr:172.18.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
         inet addr:127.0.0.1 Mask:255.0.0.0
$ docker exec -it playground_web ifconfig | grep inet
         inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
         inet addr:127.0.0.1 Mask:255.0.0.0

Now check the connectivity. The Web application can reach itself:

$ docker exec -it playground_web ping -c 5 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.033 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.036 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.031 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.029 ms

But could not reach the database application (because of the different network):

$ docker exec -it playground_web ping -c 5 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.

--- 172.18.0.2 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4126ms

To connect both apps together, put them in the same network:

Before, they use different networks:

$ docker inspect --format='{{json .NetworkSettings.Networks}}' playground_web | python -m json.tool|grep NetworkID
        "NetworkID": "6742a11bff1ebcdeaee9151f146a74b1c3d77db95d4931e4e79f48f7d7f491f7"
$ docker inspect --format='{{json .NetworkSettings.Networks}}' playground_db | python -m json.tool|grep NetworkID
        "NetworkID": "c97a80b449d9b6b28ddffa0a7bd4a7938e0b8261773080ab33ae4b7ab08826b1"

Connect Web Application to network playground_bridge:

$ docker network connect playground_bridge playground_web

 Now, they use the same network:

$ docker inspect --format='{{json .NetworkSettings.Networks}}' playground_web | python -m json.tool|grep NetworkID
        "NetworkID": "6742a11bff1ebcdeaee9151f146a74b1c3d77db95d4931e4e79f48f7d7f491f7"
        "NetworkID": "c97a80b449d9b6b28ddffa0a7bd4a7938e0b8261773080ab33ae4b7ab08826b1"
$ docker inspect --format='{{json .NetworkSettings.Networks}}' playground_db | python -m json.tool|grep NetworkID
        "NetworkID": "c97a80b449d9b6b28ddffa0a7bd4a7938e0b8261773080ab33ae4b7ab08826b1"

And they can communication

$ docker exec -it playground_web ping -c 5 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.032 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.033 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.032 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.033 ms

--- 172.17.0.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4144ms
rtt min/avg/max/mdev = 0.032/0.034/0.044/0.008 ms

$ docker exec -it playground_web ping -c 5 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.134 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from 172.18.0.2: icmp_seq=4 ttl=64 time=0.052 ms
64 bytes from 172.18.0.2: icmp_seq=5 ttl=64 time=0.053 ms

--- 172.18.0.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4156ms
rtt min/avg/max/mdev = 0.052/0.069/0.134/0.033 ms

Usefull Links

https://blog.docker.com/2019/07/intro-guide-to-dockerfile-best-practices/

Ionic | App from Scratch | Linkes und Rechtes Menu

Definieren der beiden Seitenmenüs in app.html

<ion-menu [content]="contentLeft"> ....</ion-menu>
<ion-menu side="right" [content]="contentRight">....</ion-menu>
 ....

 <ion-nav [root]="rootPage" #contentLeft #contentRight swipeBackEnabled="false"></ion-nav>
<ion-menu [content]="contentLeft"> 
	....
</ion-menu> 
<ion-menu side="right" [content]="contentRight">
	....
</ion-menu> 
.... 
<ion-nav [root]="rootPage" 
	#contentLeft 
	#contentRight 
	swipeBackEnabled="false">
</ion-nav>

Zwei Schaltflächen hinzufügen

<ion-header>
   <ion-navbar>
      <button ion-button start menuToggle>
         <ion-icon name="menu"></ion-icon>
      </button>
      <ion-title>Demo of two Sidemenus</ion-title>
      <button ion-button end menuToggle="right">
         <ion-iconname="menu"></ion-icon>
      </button>
   </ion-navbar>
</ion-header>
<ion-content padding>
</ion-content>

Ergebnis

Github Repository

Hier liegt der Beispielcode.

Ionic | App from Scratch – Two Sidemenus

Prepare your starter App

ionic start App sidemenu --type angular --no-git

Change into the newly create folder and start the Ionic App

cd App
ionic serve

You will see the default Ionic Sidemenu App

The entries of the sSidemenu are defined in app.components.ts:

export class AppComponent {
	public appPages = [
		{ title: 'Home', url: '/home', icon: 'home' },
		{ title: 'List', url: '/list', icon: 'list' }
	];

The sidemenu itself and his apperance are defined in app.component.html:

<ion-app>
  <ion-split-pane contentId="main-content">
    <ion-menu contentId="main-content" type="overlay">
      <ion-header>
        <ion-toolbar>
          <ion-title>Menu</ion-title>
        </ion-toolbar>
      </ion-header>
      <ion-content>
        <ion-list>
          <ion-menu-toggle auto-hide="false" *ngFor="let p of appPages">
            <ion-item [routerDirection]="'root'" [routerLink]="[p.url]">
              <ion-icon slot="start" [name]="p.icon"></ion-icon>
              <ion-label>{{p.title}}</ion-label>
            </ion-item>
          </ion-menu-toggle>
        </ion-list>
      </ion-content>
    </ion-menu>
    <ion-router-outlet id="main-content"></ion-router-outlet>
  </ion-split-pane>
</ion-app>

The Sidemenu entries and the Icon are added in line 13 and 14 to the sidemenu.

Define two sidemenus in app.html

<ion-menu [content]="contentLeft"> ....</ion-menu>
<ion-menu side="right" [content]="contentRight">....</ion-menu>
 ....

<ion-nav [root]="rootPage" #contentLeft #contentRight swipeBackEnabled="false"></ion-nav>

Add buttons to page

<ion-header>
   <ion-navbar>
      <button ion-button start menuToggle>
         <ion-icon name="menu"></ion-icon>
      </button>
      <ion-title>Demo of two Sidemenus</ion-title>
      <button ion-button end menuToggle="right">
         <ion-iconname="menu"></ion-icon>
      </button>
   </ion-navbar>
</ion-header>
<ion-content padding>
</ion-content>
Result
Github Repository

You can find the code here

Ionic | App from Scratch

Prepare Environment

Install Node.JS

$ LATEST=18.16.0 
$ nvm install $LATEST --latest-npm node --version  
$ npm --version 
$ nvm alias latest $LATEST
$ nvm alias default $LATEST 

Install Ionic

$ npm -g install ionic@latest
$ ionic -version

Create an app from Template

ionic start --list
ionic start sidemenu sidemenu
ionic start super super

Introduction: First App

Prepare the base Application

Create basic structure from template

$ ionic start app_from_scratch sidemenu --type angular
$ cd app_from_scratch

Some name changing

To keep the structure of the filenames the same, i like to change the name for the routing module (changing the dash to a dot)

from

app-routing.module.ts

to

app-routing.module.ts

Show base app

$ ionic serve -c
bildschirmfoto-2016-11-16-um-18-04-31

Add a page

Create a new page with the name “About”

$ ionic generate page About

Add import to app.components.ts

  public appPages = [
    { title: 'Home', url: '/home', icon: 'home' },
    { title: 'List', url: '/list', icon: 'list' },
    { title: 'About', url: '/about', icon: '' }
  ];

Add item to app-routing.module.ts

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', loadChildren: './home/home.module#HomePageModule' },
  { path: 'list', loadChildren: './list/list.module#ListPageModule' },
  { path: 'about', loadChildren: './about/about.module#AboutPageModule' }
];

Save the file now, and you will see the sidemenu entry:

Looks great, but… where is the sidemenu?

Ok, if you check the home page html code (home.page.html), you will find a button for the side menu

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-menu-button></ion-menu-button>
    </ion-buttons>
    <ion-title>Home</ion-title>
  </ion-toolbar>
</ion-header>

Missing in about.page.html:

<ion-header>
  <ion-toolbar>
    <ion-title>About</ion-title>
  </ion-toolbar>
</ion-header>

So, we had to add the desired code snippet

<ion-header>
    <ion-toolbar>
      <ion-buttons slot="start">
        <ion-menu-button></ion-menu-button>
      </ion-buttons>
      <ion-title>About</ion-title>
    </ion-toolbar>
  </ion-header>

Add some Ionic Components

Look at the Ionic Preview App, or read the documentation, if you what to dive in immediately.

Or just copy some code from the documentation page and try by yourself:

bildschirmfoto-2016-11-16-um-19-01-22
bildschirmfoto-2016-11-16-um-18-58-48

We describe the steps to add additional components in detail in this blog.

Directory structure of an application

One possible way to build an app is:

  • create a base app from blank template
  • add desired pages, code and components

To find out the necessary steps to add an new page or component, look into the templates and compare a template with the blank template. the differences are the required steps to an a component.

For example, if you want to add tabs to your app, then compare the blank template with the tabs template:

$ ionic start starter_tabs  tabs  --type angular --no-deps --no-git --no-link
$ ionic start starter_blank blank --type angular --no-deps --no-git --no-link

The diff command shows the changes between the two templates:

$ diff -r -w starter_tabs starter_blank
diff -r -w starter_blank/ionic.config.json starter_tabs/ionic.config.json
2c2
<   "name": "starter_blank",
---
>   "name": "starter_tabs",
diff -r -w starter_blank/package.json starter_tabs/package.json
2c2
<   "name": "starter_blank",
---
>   "name": "starter_tabs",
Only in starter_tabs/src/app: about
diff -r -w starter_blank/src/app/app-routing.module.ts starter_tabs/src/app/app-routing.module.ts
5,6c5
<   { path: '', redirectTo: 'home', pathMatch: 'full' },
<   { path: 'home', loadChildren: './home/home.module#HomePageModule' },
---
>   { path: '', loadChildren: './tabs/tabs.module#TabsPageModule' }
8d6
< 
diff -r -w starter_blank/src/app/app.module.ts starter_tabs/src/app/app.module.ts
3c3
< import { RouterModule, RouteReuseStrategy, Routes } from '@angular/router';
---
> import { RouterModule, RouteReuseStrategy } from '@angular/router';
9d8
< import { AppComponent } from './app.component';
10a10
> import { AppComponent } from './app.component';
Only in starter_tabs/src/app: contact
diff -r -w starter_blank/src/app/home/home.module.ts starter_tabs/src/app/home/home.module.ts
0a1,2
> import { IonicModule } from '@ionic/angular';
> import { RouterModule } from '@angular/router';
3d4
< import { IonicModule } from '@ionic/angular';
5,6d5
< import { RouterModule } from '@angular/router';
< 
10a10
>     IonicModule,
13,19c13
<     IonicModule,
<     RouterModule.forChild([
<       {
<         path: '',
<         component: HomePage
<       }
<     ])
---
>     RouterModule.forChild([{ path: '', component: HomePage }])
diff -r -w starter_blank/src/app/home/home.page.html starter_tabs/src/app/home/home.page.html
3,5c3
<     <ion-title>
<       Ionic Blank
<     </ion-title>
---
>     <ion-title>Home</ion-title>
diff -r -w starter_blank/src/app/home/home.page.spec.ts starter_tabs/src/app/home/home.page.spec.ts
14,15c14
<     })
<       .compileComponents();
---
>     }).compileComponents();
diff -r -w starter_blank/src/app/home/home.page.ts starter_tabs/src/app/home/home.page.ts
6c6
<   styleUrls: ['home.page.scss'],
---
>   styleUrls: ['home.page.scss']
8,10c8
< export class HomePage {
< 
< }
---
> export class HomePage {}
Only in starter_tabs/src/app: tabs

Some differences come from the different names (starter_blank vs. starter_tabs, HomePage vs. TabsPage). The significant changes are those, which are new in the starter_tabs directory.

PostgreSQL | Getting started

Install

PostgreSQL Server

Mac OS

brew install postgres

Windows (Installer)

Windows (Zip-ARchiv)

Download postgresql from https://www.enterprisedb.com/download-postgresql-binaries

Configure

Initialize database:

initdb.exe -D ../data –-username=postgres –-auth=trust

Start the database:

pg_ctl.exe start -D ../data

Log into the database:

psql –-username=postgres

Create a password for your user:

ALTER USER postgres WITH PASSWORD ‘VeryVerySecret’;

Install adminpack extension:

CREATE EXTENSION adminpack;

Manage Users

Preparation

psql postgres

List all Users

postgres=# \du+

Create Superuser

 create role superuser superuser login password 'pAssw8rd';

Change Password

Postgres Utilities

Documentation

Working with

iPython | Getting Started

Introduction

iPython ist ein Kommandozeileninterpreter zum interaktiven Arbeiten mit der Programmiersprache Python

IDEs and Environments

Install 

Jupyter

$ virtualenv --python python3 jupyter
$ cd jupyter
$ . bin/activate
$ pip install --upgrade pip
$ pip install jupyter

Finally run jupyter

jupyter notebook

Anaconda

$ virtualenv --python python3 anaconda
$ cd anaconda
$ . bin/activate
$ wget https://repo.continuum.io/archive/Anaconda3-4.3.1-Linux-x86_64.sh | bash
jupyter notebook

Resources

Awesome Notebooks

Notebooks