Installing packages into ubuntu14.04 docker container - docker

I currently have similar images being built for virtualbox and digital ocean for dev and production (they're using packer and ansible to build). They're using Ubuntu 14.04.
I've created a docker version from the same scripts without any issue. This is going to be for a Gitlab CI environment.
When I come to install packages inside a container I get an error. Potentially to do with broken init systems? Something not running?
My initial command is /sbin/init and I've tried with and without phusion/base-image.
The error is msg: '/usr/bin/apt-get -y -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" install 'docker-engine'' failed: invoke-rc.d: unknown initscript, /etc/init.d/cgroup-lite not found.
dpkg: error processing package cgroup-lite (--configure):
(Yes, this is going to be a monolithic container rather than single-process and yes, I'm running docker from inside it - I'll be sharing docker.sock to make this work.)

So, I had a look at the code for invoke-rd.d and found this relevant snippet.
# If we're running on upstart and there's an upstart job of this name, do
# the rest with upstart instead of calling the init script.
if which initctl >/dev/null && initctl version | grep -q upstart \
&& [ -e "$UPSTARTDIR/${INITSCRIPTID}.conf" ]
then
is_upstart=1
elif test ! -f "${INITDPREFIX}${INITSCRIPTID}" ; then
## Verifies if the given initscript ID is known
## For sysvinit, this error is critical
printerror unknown initscript, ${INITDPREFIX}${INITSCRIPTID} not found.
if [ ! -e "$UPSTARTDIR/${INITSCRIPTID}.conf" ]; then
# If the init script doesn't exist, but the upstart job does, we
# defer the error exit; we might be running in a chroot and
# policy-rc.d might say not to start the job anyway, in which case
# we don't want to exit non-zero.
exit 100
fi
fi
A combination of docker replacing the init system, the inability to use upstart in an ubuntu docker container and the ubuntu package for cgroup-lite being built for upstart meant dpkg --configure was failing as the service couldn't be started.

Related

How to automatically shutdown a GCE VM after the docker container finishes?

I have a batch process (packaged in a docker image) that needs to run once a day somewhere in the cloud. Google Compute Engine (GCE) seems like a simple and easy to use option for this with it's container-optimized OS VM. This works really well, except that I cannot find an easy way to automatically shutdown the VM after the docker container finishes. You can specify a startup script but GCE seems to execute it before the container is started, so doing docker wait there does not work. I don't care that it's a docker-optimized VM. One of the other basic Linux OSs (like Debian) is fine as long as it can easily be setup with docker.
Is there an easy way of automatically shutting a Linux VM down after the docker container finishes?
As requested in the question comments, Python code to shutdown a Compute Engine instance.
Note: The Google Compute Engine Metadata server can provide the REPLACE variables in the script. Also, you do not need to wait for the results to be STOPPED, just verify that the script did not fail. You can test this program locally as well.
See this answer for tips on COS container credentials. The program below uses ADC (Application Default Credentials).
from pprint import pprint
import time
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('compute', 'v1', credentials=credentials)
# Project ID for this request.
project = 'REPLACE_WITH_PROJECT_ID'
# The name of the zone for this request.
zone = 'REPLACE_WITH_COMPUTE_ENGINE_ZONE'
# Name of the instance resource to start.
instance = 'REPLACE_WITH_COMPUTE_ENGINE_INSTANCE_NAME'
request = service.instances().stop(project=project, zone=zone, instance=instance)
response = request.execute()
pprint(response)
print('Waiting for operation to finish...')
print('Name:', response['name'])
while True:
result = service.zoneOperations().get(
project=project,
zone=zone,
operation=response['name']).execute()
print('status:', result['status'])
if result['status'] == 'DONE':
print("done.")
break;
if 'error' in result:
raise Exception(result['error'])
time.sleep(1)
I was able to avoid shutting down the VM from within the docker container by simply deploying a regular Debian VM on Compute Engine. Steps:
First, create a Debian VM on Compute Engine and pass a startup script that installs docker. Startup script:
#!/bin/bash
# Install docker. Taken from the docker documentation.
# Passed into the gcloud command that creates the VM instance.
apt-get -y remove docker docker-engine docker.io containerd runc
apt-get update
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get -y install docker-ce docker-ce-cli containerd.io
echo Done installing docker.
Second, replace that startup script with one that pulls and runs the docker image:
#!/bin/bash
...
# Get authorization to pull from artifact registry
gcloud -q auth configure-docker us-east1-docker.pkg.dev
# Pull the image and run it, then shutdown.
docker pull $image
docker rm $container
docker run -v $vol_ini:$app_ini -v $vol_log:$app_log --name $container $image
shutdown now
Now this VM can be scheduled to run the docker image on a daily basis and automatically shut itself down.

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.

Is there any way to run "pkexec" from a docker container?

I am trying to set up a Docker image (my Dockerfile is available here, sorry for the french README: https://framagit.org/Gwendal/firefox-icedtea-docker) with an old version of Firefox and an old version of Java to run an old Java applet to start a VPN. My image does work and successfully allows me to start the Java applet in Firefox.
Unfortunately, the said applet then tries to run the following command in the container (I've simply removed the --config part from the command as it does not matter here):
INFO: launching '/usr/bin/pkexec sh -c /usr/sbin/openvpn --config ...'
Then the applet exits silently with an error. While investigating, I've tried running a command with pkexec with the same Docker image, and it gives me this result:
$ sudo docker-compose run firefox pkexec /firefox/firefox-sdk/bin/firefox-bin -new-instance
**
ERROR:pkexec.c:719:main: assertion failed: (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0)
But I don't know polkit at all and cannot understand this error.
EDIT: A more minimal way to reproduce the problem is with this Dockerfile:
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y policykit-1
And then run:
$ sudo docker build -t pkexec-test .
$ sudo docker run pkexec-test pkexec echo Hello
Which leads here again to:
ERROR:pkexec.c:719:main: assertion failed: (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0)
Should I conclude that pkexec cannot work in a docker container? Or is there any way to make this command work?
Sidenote: I have no control whatsoever on the Java applet that I try to run, it is a horrible and very dated proprietary black box that I am supposed to use at work, for which I have no access to the source code, and that I must use as is.
I have solved my own problem by replacing pkexec by sudo in the docker image, and by allowing passwordless sudo.
Given an ubuntu docker image where a user called developer was created and configured with a USER statement, add these lines:
# Install sudo and make 'developer' a passwordless sudoer
RUN apt-get install sudo
ADD ./developersudo /etc/sudoers.d/developersudo
# Replacing pkexec by sudo
RUN rm /usr/bin/pkexec
RUN ln -s /usr/bin/sudo /usr/bin/pkexec
with the file developersudo containing:
developer ALL=(ALL) NOPASSWD:ALL
This replaces any call to pkexec made in a process running in the container, by a call to sudo without any password prompt, which works nicely.

zsh: command not found: dcos

I tried to install DC/OS cluster on my Mac by dcos-vagrant.
Intsallation is quite smooth, no errors found.
==> m1: sudo: chmod u+x /opt/mesosphere/bin/postflight.sh
==> m1: sudo: /opt/mesosphere/bin/postflight.sh
==> boot: DC/OS Installation Complete
==> boot: Web Interface: http://m1.dcos/
but when I opne the http://m1.dcos/, doesn't show the web-ui, show the ERR_EMPTY_RESPONSE error, and cannot find the dcos command.
GET http://m1.dcos/ net::ERR_EMPTY_RESPONSE
➜ dcos-vagrant git:(master) dcos marathon app add https://dcos.io/docs/1.7/usage/nginx.json
zsh: command not found: dcos
Anyone can help me! Thanks in advance!
dcos cannot work duo to I didn't install the dcos CLI.
intallation DC/OS CLI
To install the CLI, copy and paste into your terminal:
mkdir -p dcos
cd dcos
curl -O https://downloads.dcos.io/dcos-cli/install.sh
bash ./install.sh . https://m1.dcos
source ./bin/env-setup
Empty response from http://m1.dcos/ would seem to indicate the UI service or admin router is having issues, but the CLI working means admin router is reachable and correctly proxying components like Marathon & Mesos.
You might check the admin router logs to see if it's having trouble serving the UI html/js.
Status:
systemctl status dcos-adminrouter.service
Logs:
journalctl -u dcos-adminrouter

initctl too old upstart check

I am trying to do a syntax check on an upstart script using init-checkconf. However when I run it, it returns ERROR: version of /sbin/initctl too old.
I have no idea what to do, I have tried reinstalling upstart but nothing changes. This is being run from within a docker container (ubuntu:14.04) which might have something to do with it.
I just ran into the same issue.
Looking in the container:
root#puppet-master:/# cat /sbin/initctl
#!/bin/sh
exit 0
I haven't tested it completly yet, but I added the following to my Dockerfile:
# Fix upstart
RUN rm -rf /sbin/initctl && ln -s /sbin/initctl.distrib /sbin/initctl
I thought this link explained it pretty good:
When your Docker container starts, only the CMD command is run. The only processes that will be running inside the container is the CMD command, and all processes that it spawns. That's why all kinds of important system services are not run automatically – you have to run them yourself.
Digging around some more, I found an official Ubuntu image containing a working version of upstart:
https://registry.hub.docker.com/_/ubuntu-upstart/

Resources