23 December, 2019

Third stop on the Docker learning train - Quickstart: Compose and ASP.NET Core with SQL Server

The third stop on my Docker learning train is a recommendation from the Docker Samples. The tutorial is titled 'Quickstart: Compose and ASP.NET Core with SQL Server'. This is going to be a whistle-stop.

This tutorial shows using the Docker Engine running on Linux to set up and run an ASP.NET Core application using a .NET Cor SKD image and SQL Server on Linux image. The tutorial makes use of Docker Compose for defining and running multiple container applications.

The tutorial references an older version (2.1) of the .NET Core libraries. My computer is running a newer (3.1) version of the .NET Core libraries. I wanted to see what error messages and problems running this setup would be.

The first change I made was to the docker-compose.yml file. I changed the port from 8000 to 9090 because I already had a different container using port 8000 and 9000. The second change made was in the "startup.cs" file. I commented out the setting up the connection variable. I moved the value of the connection to the "DefaultConnection" in the "appsettings.json" file. I needed to make a few more changes to the rest of the "ConfigureServices" method.


public void ConfigureServices (IServiceCollection services) {
    // Database connection string.
    // Make sure to update the Password value below from "Your_password123" to your actual password.
    // var connection = @"Server=db;Database=master;User=sa;Password=Your_password123;";

    services.Configure (options => {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
        });

    services.AddDbContext (options =>
        options.UseSqlServer (
            Configuration.GetConnectionString ("DefaultConnection")));
    services.AddDefaultIdentity ()
        .AddEntityFrameworkStores ();

    services.AddMvc ().SetCompatibilityVersion (CompatibilityVersion.Version_2_1);
}

On my computer, I encountered an issue with running 'docker-compose build'. The error message was
"ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable."
After a bit of research, I came to find out that this is a fairly generic and common message that could have several possible causes. For me, it turned out the I needed to change the permissions on the "docker.sock" file. I fixed the issue be running
sudo chmod 666 /var/run/docker.sock

The running of the command 'docker-compose up' wrote many messages to the console that gives the appearance of that the application and database are running. I can also have a couple of active containers. When I navigate to localhost:9090, the browser displays a "This site can't be reached" message. I am not going to take the time to figure out the problem at this time.



References 

Docker Compose - "Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration."

The article on Medium "If you faced an issue like 'Couldn't connect to Docker daemon at http+docker://localunixsocket -- is it running?'..." was helpful in dealing with an error from running 'docker-compose build'





19 December, 2019

Second stop on the Docker learning train - Dockerize an ASP.NET Core application

The second stop on my Docker learning train is a recommendation from the Docker Samples. The tutorial is titled 'Dockerize an ASP.NET Core application'.

When I first read through the tutorial, I figured this was going to be quick and easy. Due to making a few mistakes in creating the Dockerfile, I ended up with a few lessons learned.

The first lesson I learned was to read the output from running the docker build command carefully. It was interesting to see that the Docker daemon creates and removes intermediate containers.

The next lesson was when a container reports an error code 145 carefully double-check the Dockerfile. Pay close attention to what is being used for the DotNet Core runtime. The 'SDK' should be used for the restore and publish command while 'ASPNET' should be used for the runtime.

Another lesson learned is to use '.dockerignore' file to keep from unnecessary files from being included in the image.

The last lesson was to use interactive mode. The tutorial did not go through the steps I needed to do a bit of research to figure it out. The Alpine image does not include bash. I modified the Dockerfile to pull in bash and a few other tools. Rebuilt the image. The used the interactive mode switches to get a command prompt.

Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /app/aspnetapp

# copy csproj and restore as distinct layers
COPY myWebApp/*.csproj ./
RUN dotnet restore

# copy everything else and build app
COPY myWebApp/. ./
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapp/out .

# Uncomment the following line to install bash and other tools useful for debugging
RUN apk add --no-cache bash coreutils grep sed

ENTRYPOINT ["dotnet", "myWebApp.dll"]

Command to build the image.

docker build -t {image name} .

Command to start the container in interactive mode and to override the default entry point

docker run -it --entrypoint /bin/bash {image name}

Reference

.dockerignore file
"Before the docker CLI sends the context to the docker daemon, it looks for a file named .dockerignore in the root directory of the context. If this file exists, the CLI modifies the context to exclude files and directories that match patterns in it. This helps to avoid unnecessarily sending large or sensitive files and directories to the daemon and potentially adding them to images using ADD or COPY." - https://docs.docker.com/engine/reference/#dockerignore-file

14 December, 2019

First stop on the Docker learning train - Docker for beginners

The first stop on my Docker learning train is from the Docker Samples with the tutorial Docker for beginners.

The tutorial has four chapters:
  • Setup
  • 1.0 Running your first container
  • 2.0 Webapps with Docker
  • 3.0 Deploying an app to a Swarm

Setup

The Setup chapter makes sure that Docker is installed and running on my machine. The tutorial points back to the Docker documentation for the installation steps. To verify that Docker is working run the following:
docker run hello-world

1.0 Running your first container

The key topics for this chapter include:
  • How to run a docker container.
  • How to list containers.
  • How to inspect a container.

Docker CLI commands

  • docker pull - pulls an image or repository from a registry
  • docker run - runs a container
    • This command can also pull a container
    • By default, the interactive shell will exit after running a script. Use the '-it' switch to keep the shell open.
      • Example: 
        docker run -it alpine /bin/sh
        
  • docker ps - list containers
    • By default, the command lists the running containers. 
    • To list all the containers use the switch '-a'
      • Example:
        docker ps -a
  • docker inspect - returns low-level information about a docker container

Terms

image - Docker images are the basis of containers. An Image is an ordered collection of root filesystem changes and the corresponding execution parameters for use within a container runtime. An image typically contains a union of layered filesystems stacked on top of each other. An image does not have state and it never changes. - Docker Glossary
container - A container is a runtime instance of a docker image.
A Docker container consists of
  • A Docker image
  • An execution environment
  • A standard set of instructions
The concept is borrowed from Shipping Containers, which define a standard to ship goods globally. Docker defines a standard to ship software. - Docker Glossary

2.0 Webapps with Docker

This chapter is broken into a few sections.

2.1 Run a static website in a container

Key topics for the section include:
  • How to run a container in detached mode.
  • How to publish the ports the container exposes.
  • How to name a container.
  • How to pass environment variables to the container.
  • How to stop a container.
  • How to remove a container.

2.2 Docker Images

Key topics for this section include:
  • What is a Docker image?
  • How to use 'tag' to pull a specific version of a container.

2.3 Create your first image

Key topics for this section include:
  • How to write a Dockerfile.
  • How to build the image.
  • How to run the image.
Notes about Dockerfiles

  • By convention, an instruction is written in UPPERCASE. This makes it easier to distinguish an instruction from an argument. 
  • Docker runs instructions in order.
  • A Dockerfile must begin with a 'FROM' instruction. 
  • Lines the begin with '#' are treated as a comment.
  • Guide: Best practices for writing Dockerfiles

Terms

base image - A base image has no parent image specified in its Dockerfile. It is created using a Dockerfile with the FROM scratch directive.
Child images are images that build on base images and add additional functionality. 
Official images are Docker sanctioned images. 
User images are images created and shared by users like you.
Dockerfile is a text document that contain all the commands a user could call on the command line to assemble an image. 

Docker CLI commands

  • docker run
    • -d - detached mode
    • -P - publish exposed container ports to random ports on the host
    • -e - pass environment variables to the container.
    • --name - allows a name to be specified for the container
  • docker stop - stops one or more containers
  • docker rm - removes one or more containers
    • -f - Force removal of a running container
  • docker port - List port mapping or a specific mapping for a container
  • docker images - list images
  • docker pull 
    • by default, pull gets the latest version
    • to get a specific version include the tag 
      • Example: 
        docker pull ubuntu:12.04
        
  • docker search - search the Docker Hub for images
  • docker build - build an image from a Dockerfile
    • -t - Name and optional a tag in the 'name:tag' format
  • docker login - Log into a Docker registry
  • docker push - Push an image or a repository to a registry

3.0 Deploy an app to a Swarm

Key topics for this chapter include:

  • How to create a swarm.
  • How to deploy. 

I was unable to make the example work properly on my machine. The docker swarm and docker stack executed without reporting any errors. The command 'docker ps' reports multiple active containers. I will need to come back to this tutorial at a later date to investigate further.

Terms

swarm - A swarm is a cluster of one or more Docker Engines running in swarm mode
Docker Swarm - Do not confuse Docker Swarm with the swarm mode features in Docker Engine.
Docker Swarm is the name of a standalone native clustering tool for Docker. Docker Swarm pools together several Docker hosts and exposes them as a single virtual Docker host. It serves the standard Docker API, so any tool that already works with Docker can now transparently scale up to multiple hosts.
Also known as : docker-swarm
swarm mode - Swarm mode refers to cluster management and orchestration features embedded in Docker Engine. When you initialize a new swarm (cluster) or join nodes to a swarm, the Docker Engine runs in swarm mode.

Docker CLI Commands







07 December, 2019

Learning a bit about Docker


What is Docker?

Docker is a tool to develop, ship and run applications. The heart of Docker is the container. A Docker container contains all the parts needed to run an application.

Install

I am currently running Pop!_OS 19.10. Which made installing Docker a bit more interesting. Pop!_OS 19.10 is based on Ubuntu 19.10. The official Docker documentation shows support for Ubuntu 19.04. For the most part, I followed the official documentation to install. When it came time to add the source I used the following.

sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu disco stable"

The rest of the instructions were easy to follow and didn't require any modifications.

I also run the 'Optional Linux post-installation steps'. These steps should allow me to run docker commands from a terminal without preface a command without the 'sudo' keyword. For some reason, this is not working for me. I have verified that the group exists and my user account is part of the group. Additional research is needed.

Reading

I spent a bit of time reading through the official Docker documentation. There is a lot of information to absorb. There is way too much information to summarize in a single blog post. I am going to need a break the information down into smaller chunks.

Plan

From the Docker Samples work the following tutorials:

From Play with Docker Classroom work the following tutorials:
From Docker Curriculum work the following tutorials:

Resources

02 September, 2019

Setting up Home Assistant

What is Home Assistant?

"Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server." - https://www.home-assistant.io

I like to think of Home Assistant as the central hub to connect and control devices around my home. Most of the home automation items (light bulb and light switches) are just fancy remote-controlled devices. The hub should give me a way to control devices from different vendors, a way to step automations (turn on lights when at certain times), and a little future-proofing. 

Why Home Assistant?

Basically three reasons, the first is I have a Raspberry Pi 3B+ not dedicated to anything yet. The second is the price of Home Assistant. Lastly, I want the ability to tinker with the software.

Setup


  • Downloaded install image 
    • Raspberry Pi 3 Mobel b and B+ 64bit
  • Used GParted to repartition an old 32GB SD card
  • Flashed the image to the SD card
  • Connected or inserted the Raspberry Pi to 
    • Monitor
    • Keyboard
    • Mouse
    • Network - hard wire for now
    • the newly flashed SD card
    • power
  • Wait
    • This can take a while
      • Allow 20 or so minutes 
      • An updated version of the software is being downloaded and installed
      • I got the message 'IPv6: ADDRCOF(NETDEV_UP): wlan0: link is not ready'. 
        • I cycled the power to the Pi.
        • Same message appeared
        • hit return a few times
        • got a login prompt
        • the default username is root

  • Add wireless
    • Using the info from 'Using nmcli to set a static IPV4 address'
    • Got to Hassio login prompt then ran the following commands
      • login
      • nmcli connection show
      • nmcli radio
      • nmcli device
      • nmcli device wifi rescan
      • nmcli device wifi list
      • nmcli device wifi connect {SSID Nane} password {password}
      • nmcli device 
      • nmcli con edit "{connection Name}"
        • print ipv4
        • set ipv4.addresses {IP of my choice}
        • set ipv4.dns {DNS address}
        • set ipv4.gateway {gateway address}
        • save
        • print ipv4
        • quit
      • nmcli con reload
    • rebooted the Pi
      • unplugged the hardwire
      • Tested wireless
        • navigated to {IP}:8123
  • First-time setup
    • After navigating to IP:8123
    • followed prompts on the screen

Resources

Home Assistant


balenaEtcher
GParted
nmcli

12 May, 2019

Today on the bench, I have the HC-SR04 Ultrasonic Range Sensor connected to a Raspberry Pi 3 Model B running DietPi.



The HC-SR04 sensor has four pins (VCC, Trig, Echo, Gnd) that need to be connected to the Raspberry Pi. VCC gets connected to one of the 5v pins and Gnd (ground) gets connected to on the of the ground pins on the Rasberry Pi. This leaves Trig (Trigger) and Echo to be connected to the Rasberry Pi.

There is a minor point that needs to be considered before connecting the Trig and Echo pins to the Raspberry Pi. The GPIO headers on the Raspberry Pi can only safely handle 3.3v. The sensor is going to send the signal back using 5v. I need a way to bring 5 volts down to something under 3.3 volts. One way to do this is with a voltage divider. All I need is a couple of resistors, jumper wires, and some math. The math will be handled by the Voltage Divider Calculator. In my stock of resistors, I can see that I have a lot of 1K resistors. I will use one of those. Into the voltage divider calculator goes 5v for the voltage source, 3.3v for the output voltage, and 1K for resistance 1. The results of the calculation gave me a value of just under 2K for resistance 2.

I connected the Trig pin on the sensor to one of the open BCM pins. Now for the tricky part, I connected ground to one leg of the 2K resistor. The other leg connects to a jumper wire going to an open BCM pin on the Raspberry Pi. I then connected the Echo pin of the sensor to one leg of the 1K resistor. The other leg of the 1K resistor gets connected to the jumper wire that I connected the 2K resistor to.





This takes care of the wiring up of the sensor. Now we get to move on to writing some code.

Over in GitHub, I created a repo named go_rpi. In the devices folder, there is a file named 'hcsr04.go'. This code file contains the code for interacting with the HC-SR04 sensor. I am taking advantage of the go-rpio library from Stian Eikeland to access the GPIO-pins. The heart of the code is the 'measure' function. This function coordinates the actions for initializing the pins to a low state, triggering the pulse, capturing the time it takes the signal to go out and back, and calculating the distance.

Resources

Datasheet on HC-SR04

Voltage Divider

Blog Posts

GitHub







04 May, 2019

Using Go to read the temperature from R1820 on a Raspberry Pi running DietPi

The other day, I came across an electronic component labeled with 'RW1820'. The component is a digital temperature sensor. I figured it would fun to see if I could write a program in Go to read the value from the sensor and to display the temperature onscreen.

The Component



Wiring it Up

The little breakout board that the chip is attached to has three pins labeled 'G', 'R', and 'Y'. The 'G' pin goes to ground, the 'R' pin goes to +5V DC, and the 'Y' pin goes to Signal. In my case, the signal is pin 7 on the Raspberry Pi.


Enable 1-Wire

From what I have been able to learn the sensor uses 1-Wire for the communications.

I am running DietPi on the Raspberry Pi so I could not use the standard 'raspi-config' or the 'Raspberry Pi Configuration' in Raspbian. This left me with the option of adding

dtoverlay=w1-gpio

to the '/boot/config.txt' file. Just a quick edit of a file and I should be good to go. It turns out that on DietPi you need to edit the file '/DietPi/config.txt' in order to have the change survive a reboot.

Once dtoverlay is added to 'DietPi/config.txt' file, the Rasberry Pi will start communicating with the device. Take a look in the folder '/sys/bus/w1/devices'. One of the folders will start with '28-' that folder will contain a file name 'w1-slave' if you read the content of that file you will get something like

72 01 4b 46 7f ff 0e 10 57 : crc=57 YES
72 01 4b 46 7f ff 0e 10 57 t=23125

Notice the 't=' at near the end of the second line. This is the temperature in Celsius. This temperature is also missing a decimal point.

Go Code


Misc

The RW1820 is very similar to the DS18B20. There is a lot more information about the DS18B20. 

Resources

Rayway International - Chinese
RW1820 Datasheet - English
1-Wire
Enable 1-Wire Interface on the Raspberry Pi
DietPi
W1-GPIO - One-Wire Interface
Introduction to DS18B20

12 April, 2019

Experimenting blinking an LED with Gobot and Raspberry Pi

In the post 'Playing with Gobot on a Raspberry Pi', I got a Go program running on a Raspberry Pi. In this post, I am going to continue experimenting with different ways to use the Gobot framework to flash a LED.

Experiment - blink multiple sequences

In this experiment, I want to flash the LED three times rapidly then blink the LED continuously.

I created two functions. The first function flashes a LED rapidly three times. To accomplish this, I used a for loop and the sleep function. The second function flashed the LED every second. The 'work' variable calls the two new functions.

Here is the code

Experiment - changing brightness

Let's try something a little bit more complex. I want to be able to control the brightness of the LED. The first thing I did grab the example code (api_led_brightness) from Gobot. My first attempt at running the code failed. The code compiled and seems to run but the LED would not change brightness. It took a bit of head scratching before I remembered the Gobot documentation said something about PWM.

The Gobot documentation references pi-blaster. I found that I needed to setup pi-blaster to get the PWM working.

Once I got pi-blaster running on the Raspberry Pi, the example code from Gobot worked. I did encounter a minor weirdness. When I exit the running program, the LED goes to full brightness.

Resources



07 April, 2019

Playing with Gobot on a Raspberry Pi

A few days ago, I came across the Gobot website. Gobot is a framework written in the Go Programming Language (golang) to work with robots, drones and the Internet of Things (IoT). Gobot work on several different platforms including the Raspberry Pi. 

After grabbing a Raspberry Pi and an SD Card that I had laying around. My first step was to download DietPi and burn it to the SD Card. The 'Getting Started' page was easy to follow and had me running a lightweight version of Linux in short order. 

After digging through the Gobot documentation for a bit, I figured that I had enough knowledge to be dangerous. The rough plan is to setup a simple circuit and control that circuit with a simple go program running on a Rasberry Pi. The Gobot documentation has an example of flashing a LED using Rasberry Pi. In the past, I followed the 'Turning on an LED with your Raspberry Pi's GPIO Pins' tutorial from The PiHut with good results. 

It was time to get out some electronics parts. I grabbed a breadboard, a 330 Ohm resistor, a red LED, and a few Male-Female jumpers wires. 

I am using a Raspberry Pi 3 Model V1.2. From pin 12 on the Pi the orange jumper goes to the anode (long) leg of the LED. The cathode (short) leg goes to the resistor. The resistor is connected to the yellow jumper which is connected to pin 14 (ground) on the Pi. The following picture shows the setup. Please note that the blue and green jumper wires are not connected to anything.





My next step was to copy the example code from Gobot into a file on my computer. I changed the example code to use pin 12 and saved the change.

The Gobot documentation shows the compiler switches needed to create a binary that can run on a Rasberry Pi. I used the following.

GOARM=7 GOARCH=arm GOOS=linux go build {filename.go}

After copying the file binary to the Rasberry Pi, I ran the file using a terminal and the LED began to flash.


References




Challenging myself to learn something new

I have recently set a big challenge for myself. I want to know about Machine Learning . To add to the challenge, I am trying out usin...