How to capture docker version in powershell cross platform - docker

I'm trying to write a powershell script that gets the version of docker cross platform. This forms the basis of a build script for a larger application which is utilizing docker, so I'd like to verify that a particular version of docker is installed.
Function Exec([Parameter(Mandatory = 1)][scriptblock]$command, $message = '') {
& $command;
if ($global:LastExitCode -ne 0) {
if ($message.Length -eq 0) {
throw "$command exited with code $global:LastExitCode."
}
throw "Exited with code $($global:LastExitCode): $message"
}
}
$version = Exec { docker -v }
This has been working fine on a windows machine, running Powershell 7. It also works on an Azure Ubuntu 20.04 Build Agent. I'm trying to get this to work on a new Ubuntu 20.10 desktop box.
I'm seeing the error write /dev/stdout: permission denied
To diagnose the issue, I removed the Exec function in case that was breaking the pipe in some way, but this still creates the same error:
PS> $version = docker -v
I found this article suggesting it was something to do with needing root https://github.com/moby/moby/issues/31243 but it makes no difference if I use pwsh or sudo pwsh
The following works in bash, but I'd rather use Powershell since most of the developers using this script will be on windows.
#> VERSION=$(docker -v)
#> echo $VERSION
Software used:
Ubuntu 20.10
Docker 19.03.11 (installed with snap install docker)
Powershell 7.1.0 (installed with snap install powershell --classic)
I've tried various ways of invoking bash to get the docker version, but they all error with the same write /dev/stdout: perrmission denied:
$version = sh -c "docker -v"
$version = sh -c "RESULT=$(docker -v);echo `$RESULT"
Interestingly the following works, so I'm guessing it's something to do with powershell and docker
$version = sh -c "RESULT=$(echo 42);echo `$RESULT"
I've tried not capturing the result into a variable and it mostly works:
docker -v # works
sh -c "docker -v" # works
sh -c "RESULT=$(docker -v);echo `$RESULT" # Doesnt work!

Related

How do I remote invoke a windows command from a docker container?

I need to remotely run a command on my window's workstation from my osx workstation using docker.
Works locally:
docker run -it mcr.microsoft.com/powershell pwsh -c "Write-Host 'Hello, World'"`
Hello, World
Doesn't work remote:
docker run -it mcr.microsoft.com/powershell pwsh -c Invoke-Command -ComputerName VM-CHIP -ScriptBlock { Write-Host 'Hello, World' }
Invoke-Command: This parameter set requires WSMan, and no supported WSMan client library was found. WSMan is either not installed or unavailable for this system.
When I try within the container
docker run -it mcr.microsoft.com/powershell
PowerShell 7.2.8
Copyright (c) Microsoft Corporation.
https://aka.ms/powershell
Type 'help' to get help.
PS /> Install-Module -Name PSWSMan
Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from 'PSGallery'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A
PS /> Install-WSMan
WARNING: WSMan libs have been installed, please restart your PowerShell session to enable it in PowerShell
PS /> Invoke-Command -ComputerName VM-CHIP -ScriptBlock { Write-Host 'Hello, World' }
it fails with
OpenError: [VM-CHIP] Connecting to remote server VM-CHIP failed with the following error message : MI_RESULT_FAILED For more information, see the about_Remote_Troubleshooting Help topic.
I'm confused what the structure is to run this within a single command intead of having to open interactive, and more importantly what am I missing to successfully execute the command on the remote machine instead of this MI_RESULT_FAILED error. Or is this not possible/supported?

Linux Ash Shell script to check if certain package is installed & called via docker

I'm trying to run docker on embedded Linux running OpenWRT.
Since the embedded Linux is a "resource constraint" I don't want Docker to install already installed packages, therefore I want to call a custom shell script with docker:
RUN $CMD_STRING = $(gcc)
RUN $CMD_OUTPUT=$(${CMD_STRING} -version)
RUN if [[ ${CMD_OUTPUT} == *"not found"* ]]; echo ${CMD_STRING} "was NOT FOUND, Installing..."
opkg update
opkg install gcc
fi
I will like a similar simple if/else structure.
I keep getting:
-ash: gcc: not found
-ash: -rw-r--r--: not found
I don't have some OpenWRT for test but this may work if its only an "ash" and "docker" problem. I tested it on alpine since it also have ash (from busybox).
Dockerfile:
from alpine:latest
RUN ash -c "if ! gcc 2>/dev/null; then echo 'not found..'; echo 'installing..'; fi"
Build it:
docker build .
Sending build context to Docker daemon 3.072kB
Step 1/2 : from alpine:latest
---> 389fef711851
Step 2/2 : RUN ash -c "if ! gcc 2>/dev/null; then echo 'not found..'; echo 'installing..'; fi"
---> Running in 2c47bee97dfc
not found...
installing..
Removing intermediate container 2c47bee97dfc
---> 35e698d1aea6
Successfully built 35e698d1aea6
You have extra spaces in your first command, and shouldn't be using a variable name with a dollar sign at the beginning. I think you probably also don't want to be assigning that with $(), since you haven't tested if it exists yet. Trying to run a command to see if it exists also isn't a great way to go about it. You can see if a program is installed like this:
if ! command -v gcc &> /dev/null; then
opkg install gcc
fi
(That's POSIX-compatible so should work in ash.)
You could also run opkg list-installed and check the output (see the docs) which may be useful for packages that aren't executables in your PATH.

Docker TICK Sandbox does not provide UDF Python functionality

I'm running this docker image to use the TICK Kapacitor locally.
The problem I face is that when I try to use User Defined Functions, e.g any of these examples I get the error message that /usr/bin/python2 does not exist.
I add the following to the kapacitor.conf:
[udf.functions]
[udf.functions.tTest]
prog = "/usr/bin/python2"
args = ["-u", "/tmp/kapacitor_udf/mirror.py"]
timeout = "10s"
[udf.functions.tTest.env]
PYTHONPATH = "/tmp/kapacitor_udf/kapacitor/udf/agent/py"
Further attempts from my side including altering the image used to build Kapacitor to install python works but the agent seems to fail to compile anyway.
Is there anyone who managed to get UDFs running using the Kapacitor Docker image?
Thanks
Docker image from the official repository: docker pull kapacitor does not have python installed inside. You can verify this by running shell in the container:
PS> docker exec -it kapacitor bash
and execute one of the command options:
$ python -VERSION
$ python: command not found
or
$ readlink -f $(which python) | xargs -I% sh -c 'echo -n "%:"; % -V'
$ readlink: missing operand
or
$ find / -type f -executable -iname 'python *'
void returns. And oppositely if python is available, commands return version and list of executable files
Note: Here and further all command snippets are given for Powershell on Windows. And all command snippets inside docker container are given for bash shell as Linux images are used.
Basicly, there is two options to get kapacitor image with python inside to execute UDFs:
Install the python in the kapacitor image, i.e. build new docker image from very kapacitor image.
Example could be found here:
Build a new verion of kapacitor image from one of the python official images
The second option is more natural as you get consistent python installation and keep efforts on doing work of installing python which already done by the docker community.
So following option 2 we'll perform:
Examine the Dockefile of the official kapacitor image
Choose an appropriate python image
Create new project and Dockerfile for kapacitor
Build and Check the kapacitor image
Examine Dockefile of official kapacitor image
General note:
For any image, the original Dockerfiles can be obtained in this way:
https://hub.docker.com/
-> Description Tab
-> Supported tags and respective Dockerfile links section
-> each of the tags is a link that leads to the Dockerfile
So for kapacitor everything is in the influxdata-docker git repository
Then in the Dockerfile we find that the image is created based on
FROM buildpack-deps: stretch-curl
here:
buildpack-deps
the image provided by the project of the same name https://hub.docker.com/_/buildpack-deps
curl
This variant includes just the curl, wget, and ca-certificates packages. This is perfect for cases like the Java JRE, where downloading JARs is very common and
  necessary, but checking out code isn't.
stretch
short version name of the OS, in this case Debian 9 stretch https://www.debian.org/News/2017/20170617
Buildpack-deps images are in turn built based on
FROM debian: stretch
And Debian images from the minimum docker image
FROM: scratch
Choose appropriate python image
Among python images, for example 3.7, you can find similar versions inheriting from buildpack-deps
FROM buildpack-deps: stretch
Following the inheritance, we'll see:
FROM buildpack-deps: stretch
FROM buildpack-deps: stretch-smc
FROM buildpack-deps: stretch-curl
FROM debian: stretch
In other words, the python: 3.7-stretch image only adds functionality to the Debian compared to the kapacitor image.
This means that we can to rebuild kapacitor image on top of the python image: 3.7-stretch with no risk or gaining incompatibility.
Docker context folder preparation
Clone the repository
https://github.com/influxdata/influxdata-docker.git
Create the folder influxdata-docker/kapacitor/1.5/udf_python/python3.7
Copy the following three files into it from influxdata-docker/kapacitor/1.5/:
Dockerfile
entrypoint.sh
kapacitor.conf
In the copied Dockerfile FROM buildpack-deps: stretch-curl replace with FROM python: 3.7-stretch
Be carefuly! If we work on Windows and because of scientific curiosity open the entrypoint.sh file in the project folder, then be sure to check that it does not change the end-line character from Linux (LF) to Windows variant: (CR LF).
   Otherwise, when you start the container later, you get an error:
or in the container log:
exec: bad interpreter: No such file or directory
or if you'll start debugging and, running the container with bash, will do:
$ root # d4022ac550d4: / # exec /entrypoint_.sh
$ bash: /entrypoint_.sh: / bin / bash ^ M: bad interpreter: No such file or directory
Building
Run PS> docker build -f. \ Dockerfile -t kapacitor_python_udf
Again, in case of Windows environment
If during the build execution an error occurs of the form:
E: Release file for http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease is not valid yet (invalid for another 9h 14min 10s). Updates for this repository will not be applied.
then your computer clock probably went out of sync and/or Docker Desktop incorrectly initialized the time after the system returned from sleep. See the issue)
To fix it, restart Docker Desktop and / or Windows settings -> Date and time settings -> Clock synchronization -> perform Sync
You can also read more here
Launch and check
Launching the container with the same actions as for the standard image. Example:
PS> docker run --name=kapacitor -d `
--net=influxdb-network `
-h kapacitor `
-p 9092:9092 `
-e KAPACITOR_INFLUXDB_0_URLS_0=http://influxdb:8086 `
-v ${PWD}:/var/lib/kapacitor `
-v ${PWD}/kapacitor.conf:/etc/kapacitor/kapacitor.conf:ro `
kapacitor
Check:
PS> docker exec -it kapacitor_2 bash
$ python -VERSION
$ Python 3.7.7
$ readlink -f $(which python) | xargs -I% sh -c 'echo -n "%:"; % -V'
$ /usr/local/bin/python3.7: Python 3.7.7

Using Docker for Windows in Jenkins Declarative Pipeline

I am setting up a CI workflow with Jenkins declarative pipeline and Docker-for-Windows agents through Dockerfile.
Note: It is unfortunately currently not a solution to use a Linux-based docker daemon, since I need to run Windows binaries.
Setup: Jenkins master runs on Linux 16.04 through Docker. Jenkins build agent is
Windows 10 Enterprise 1709 (16299.551)
Docker-for-Windows 17.12.0-ce
Docker 18.x gave me headaches when trying to use Windows Containers, so I rolled back to 17.x. I still had some issues when trying to run with Jenkins and nohup not being on path, but it was solved by adding Git binaries to Windows search path (another reference). I suspect my current issue may be related.
Code: I am trying to initialize a Jenkinsfile and run a simple hello-world-printout within.
/Jenkinsfile
pipeline {
agent none
stages {
stage('Docker Test') {
agent {
dockerfile {
filename 'Dockerfile'
label 'windocker'
}
}
steps {
println 'Hello, World!'
}
}
}
}
/Dockerfile
FROM python:3.7-windowsservercore
RUN python -m pip install --upgrade pip
Basically, this should be a clean image that simply prints "Hello, World!". But it fails on Jenkins!
Output from the log:
[C:\jenkins\workspace\dockerfilecd4c215a] Running shell script
+ docker build -t cbe5e0bb1fa45f7ec37a2b15566f84aa9bd08f5d -f Dockerfile .
Sending build context to Docker daemon 337.4kB
Step 1/2 : FROM python:3.7-windowsservercore
---> 340689b75c39
Step 2/2 : RUN python -m pip install --upgrade pip
---> Using cache
---> a93f446a877f
Successfully built a93f446a877f
Successfully tagged cbe5e0bb1fa45f7ec37a2b15566f84aa9bd08f5d:latest
[C:\jenkins\workspace\dockerfilecd4c215a] Running shell script
+ docker inspect -f . cbe5e0bb1fa45f7ec37a2b15566f84aa9bd08f5d
.
Cannot run program "id": CreateProcess error=2, The system cannot find the file specified
The issue is, that windows is not supported at the moment. It is calling the linux "id" command to get the current user id.
There is an open Pull Request and JIRA Ticket at Jenkins to support Windows docker pipeline:
https://issues.jenkins-ci.org/browse/JENKINS-36776
https://github.com/jenkinsci/docker-workflow-plugin/pull/148

How can I use a dredd docker image interactively?

I would like to use this docker container apiaryio/dredd instead of the npm package dredd. I am not familiar with running and debugging npm based docker images. How can I run the basic usage example of the npm package "Quick Start" section
$ dredd init
$ dredd
if I have a Swagger file instead of the api-description.apib in $PWD/api/api.yaml or $PWD/api/api.json?
TL;DR
Run dredd image as a command line. Dredd Image at Docker Hub
docker run -it -v $PWD:/api -w /api apiaryio/dredd init
[Optional] Turn it into a script:
#!/bin/bash
echo '***'
echo 'Root dir is /api'
export MYIP=`ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`
echo 'Host ip is: ' $MYIP
echo 'Configure URL of tested API endpoint: http://api-srv::<enpoint-port>. Set api-srv to point to your server.'
echo 'This script will set api-srv to docker host machine - ' $MYIP
echo '***'
docker run -it --add-host "api-srv:$MYIP" -v $PWD:/api -w /api apiaryio/dredd dredd $1
[Optional] And put this script in a folder that is in your PATH variable and create an alias for short it
alias dredd='bash ./scripts/dredd.sh'
Code at Github gist.

Resources