How do I install a specific version of Chrome in a Dockerfile? - docker

Have a Dockerfile that installs from a python image and then I need it to install a specific (not latest) version of Google Chrome.
Here's what I have:
FROM python:3.6
# Tools
RUN apt-get update \
&& apt-get install -y vim less \
&& apt-get clean
# https://github.com/SeleniumHQ/docker-selenium/blob/master/NodeChrome/Dockerfile.txt
#============================================
# Google Chrome
#============================================
# can specify versions by CHROME_VERSION;
# e.g. google-chrome-stable=53.0.2785.101-1
# google-chrome-beta=53.0.2785.92-1
# google-chrome-unstable=54.0.2840.14-1
# latest (equivalent to google-chrome-stable)
# google-chrome-beta (pull latest beta)
#============================================
ARG CHROME_VERSION="google-chrome-stable"
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
&& apt-get update -qqy \
&& apt-get -qqy install \
${CHROME_VERSION:-google-chrome-stable} \
&& rm /etc/apt/sources.list.d/google-chrome.list \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/*
The Chrome installation steps were taken from here (as seen in the comments) and even using the version in the example I get the error
E: Version '53.0.2785.101-1' for 'google-chrome-stable' was not found
Tried other versions from https://chromereleases.googleblog.com/ and nothing works.
Do you know of a different way to install a specific version or if I'm doing something wrong with these steps?

This took me a while to find, but you're installing from Google's repository and they only keep the latest versions of Google Chrome in their repositories. You could probably search for 3rd party repositories that have older versions of Chrome, but I personally wouldn't recommend that.
The current version is 75.0.3770.100-1 for google-chrome-stable at the time of this post. Will that not work for you?
Lastly, I directly copied your dockerfile and it worked for me with the latest build of google-chrome-stable installed on the image. How were you running docker?
Here was my process:
Copied your docker file directly into ./Dockerfile
docker build ./
docker image ls
Copied my image id (90206843f24e in my case)
docker run --entrypoint "/bin/bash" -it 90206843f24e
You'll be dropped in a root shell on the docker image to "poke" around
run google-chrome -version to verify the above version is installed
I hope this works for you. Good luck and keep us posted!

Related

How can I build a similar docker image based on alpine that works on ubuntu?

I am trying to rewrite a Dockerfile (https://github.com/orangefoil/rcssserver-docker/blob/master/Dockerfile) so that it uses alpine instead of ubuntu. Goal is to reduce the file size.
In the original image the robocup soccer server is built from scratch using g++, flex, bison, etc.
FROM ubuntu:18.04 AS build
ARG VERSION=16.0.0
WORKDIR /root
RUN apt update && \
apt -y install autoconf bison clang flex libboost-dev libboost-all-dev libc6-dev make wget
RUN wget https://github.com/rcsoccersim/rcssserver/archive/rcssserver-$VERSION.tar.gz && \
tar xfz rcssserver-$VERSION.tar.gz && \
cd rcssserver-rcssserver-$VERSION && \
./bootstrap && \
./configure && \
make && \
make install && \
ldconfig
I tried to do the same on alpine and had to exchange some packages:
FROM alpine:latest
ARG VERSION=16.0.0
WORKDIR /root
# Add basics first
RUN apk — no-cache update \
&& apk upgrade \
&& apk add autoconf bison clang-dev flex-dev boost-dev make wget automake libtool-dev g++ build-base
RUN wget https://github.com/rcsoccersim/rcssserver/archive/rcssserver-$VERSION.tar.gz
RUN tar xfz rcssserver-$VERSION.tar.gz
RUN cd rcssserver-rcssserver-$VERSION && \
./bootstrap && \
./configure && \
make && \
make install && \
ldconfig
Unfortunately, my version doesn't work yet. It fails with
/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lrcssclangparser
From what I found so far, this can happen, if dev packages are not installed (see ld cannot find an existing library), but I changed to dev packages where I could find them and still no luck.
So, my current assumption is that ubuntu has some package installed, that I need to add in my alpine image. I would exclude a code problem, since the ubuntu version works.
Any ideas, what could be missing? I would also be happy to understand how to compare the packages myself, but the package namings are not the same in ubuntu and alpine, so I find it pretty hard to figure this out.
You should break this up using a multi-stage build. In the image you're building now, the final image contains the C toolchain and all of the development libraries and headers that those -dev packages install; you don't need any of those to actually run the built application. The basic idea is to build the application exactly as you have it now, but then COPY only the built application into a new image with fewer dependencies.
This would look something like this (untested):
FROM ubuntu:18.04 AS build
# ... exactly what's in the original question ...
FROM ubuntu:18.04
# Install the shared libraries you need to run the application,
# but not -dev headers or the full C toolchain. You may need to
# run `ldd` on the built binary to see what exactly it needs.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --assume-yes --no-install-recommends \
libboost-atomic1.65.1 \
libboost-chrono1.65.1 \
# ... more libboost-* libraries as required ...
# Get the built application out of the original image.
# Autoconf's default is to install into /usr/local, and in a
# typical Docker base image nothing else will be installed there.
COPY --from=build /usr/local /usr/local
RUN ldconfig
# Describe how to run a container.
EXPOSE 12345
CMD ["/usr/local/bin/rcssserver"]
Compared to the size of the C toolchain, header files, and build-time libraries, the difference between an Alpine and Ubuntu image is pretty small, and Alpine has well-documented library compatibility issues with its minimal libc implementation.

TestCafe: Chromium: Error: Unable to establish one or more of the specified browser connections

When running the E2E tests in the CI (BitBucket) using chromium:headless, they break with following error:
Error: Unable to establish one or more of the specified browser connections. This can be caused by network issues or remote device failure.
at BrowserSet._waitConnectionsOpened (/opt/atlassian/pipelines/agent/build/node_modules/testcafe/src/runner/browser-set.js:83:30)
at Promise.resolve.then (/opt/atlassian/pipelines/agent/build/node_modules/testcafe/src/runner/browser-set.js:106:35)
Here comes the weird part, the CI run the custom E2E pipeline at 9th November 2019 at 11:34pm, then at 10th November 2019 at 11:34pm it starts failing, exact same code and it was running inside the same dockerfile as the 9th Nov one.
What I have done?
I tried updating TestCafe to latest version - 1.6.1, not working
Updating Gherking-Testcafe to latest version - 2.4.2
Tried running with:
‘chromium ----no-sandbox’
‘chromium:headless ----no-sandbox’
With no success
Tried running firefox:headless, a lot of tests starts too fail, might have to dig into why they are failing...
Updated the docker container with newer versions of everything, same error
Asked TestCafe to list the browsers and Chromium is in the list
+ npx testcafe --list-browsers
firefox
chromium
The Docker file:
# using debian:jessie for it's smaller size over ubuntu
FROM debian:jessie
# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# Set environment variables
ENV appDir /var/www/app/current
# Run updates and install deps
RUN echo "deb http://packages.linuxmint.com debian import" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y -q --force-yes \
python python-pip chromium chromium-l10n firefox xvfb curl wget\
&& pip install --upgrade awscli s3cmd python-magic \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get -y autoclean
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 10.8.0
# Install NPM packages
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& npm install -g serve \
&& nvm alias default $NODE_VERSION \
&& nvm use default
# Set up our PATH correctly so we don't have to long-reference npm, node, &c.
ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
EXPOSE 1337 1338
I had to re-do our old one, because Gulp was creating issues with latest Node, so, needed a way to control the node version using NVM
Bug logged on TestCafes GitHub's page: https://github.com/DevExpress/testcafe/issues/4489
I was able to get to work by changing:
chromium:headless to 'chromium --headless --no-sandbox'
It is still weird to me how it worked one day and within 24 with the same source code, docker image, it broke! Still curious to see what the TestCafe team will find, they are tracking the issue here:
https://github.com/DevExpress/testcafe/issues/4489#issuecomment-555061246
why ----no-sandbox? Had similar issues this week with Bitbucket Pipelines where I forgot to add --no-sandbox, but adding as written seemed to fix the issue...
Also, adding a .testcafe.json file to specify your options makes writing the options a lot easier...

Same Dockerfile gives different outcomes during build

I am refactoring an angular application to switch from a VM architecture to Docker containers.
While building the container for Angular I came up with a Dockerfile to use as a builder in the multistage build. I worked like a charm on my Mac so i pushed it to our company github to be consumed by my colleagues.
The problem rise up when a colleague pulled from the repo and tried to build on his Mac (different models but more or less comparable, mine is a 2015, his is a 2016, both running Mojave).
This is the content of the dockerfile that is erroring:
# base image
FROM node:9.6.1 as builder
# install chrome for protractor tests
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
RUN apt-get update
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:fontforge/fontforge
RUN apt-get install -y google-chrome-stable
RUN apt-get install -y fontforge ttfautohint gettext
I was assuming it to build fine as it was on my laptop but when he tries to launch the build he receives some errors in the step RUN apt-get update
The container gets a 404 while trying to update systemd and exits.
We tried also to spin up a new container FROM THE SAME image docker run --rm -it node:9.6.1 /bin/bash and copy-pasting all the instructions manually in the command line and it worked fine.
1. Why two different outcomes in two very similar but still different machines?
The entire point of docker containers should be abstracting the environment and create standalone environments for your applications, so why the same Dockerfile blueprints work perfectly on my machine and do not on his?
Also the docker demon runs fine and it starts the container, the issue we have is during the system upgrade inside the container build.
2. Why on the same machine, the Dockerfile build fails while the same steps succeed if run manually?
This completely blew up my mind, i may even understand the two different machines issue, but i cannot find any logical explanation to this one: same commands fed to command line work while they don't if executed via script.
apt-get update, in particular, generates results that vary over time. These include URLs to Debian packages, and standard Debian package management practice is to remove a package from the repository listings as soon as there’s a newer version.
If you previously ran the Dockerfile up through the RUN apt-get update, and then later changed what specific packages get installed, you could wind up in a state where Docker cached the results of the update operation, but they’re no longer valid.
The usual answer to this is to make sure to run apt-get update && apt-get install in a single RUN step:
RUN apt-get update \
&& apt-get install -y software-properties-common
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN add-apt-repository -y ppa:fontforge/fontforge
RUN apt-get update \
&& apt-get install -y google-chrome-stable fontforge ttfautohint gettext

adding .net core to docker container with Jenkins

I'm trying to create a dockerfile that will build an image with .net core 2.0 and Jenkins. I'm kind of new to Docker but want to include .net core 2.0 in my container with Jenkins so I don't have to worry about .net core being installed on the target machine and can build .net core apps with Jenkins in my container. Am I missing something here?
it builds fine up until it runs the apt-get update command and I get the following error:
E: Malformed entry 1 in list file /etc/apt/sources.list.d/dotnetdev.list (component)
E: The list of sources could not be read.
I'm using the steps to install on ubuntu at this link:
https://learn.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x
My Dockerfile looks like this:
FROM jenkins
# Install .NET Core SDK
USER root
RUN mkdir -p /jenkins
WORKDIR /jenkins
ENV DOTNET_CORE_SDK_VERSION 2.0
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor >/jenkins/microsoft.gpg
RUN mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
RUN sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
RUN apt-get update
RUN apt-get install dotnet-sdk-2.0.0
As of this response you can use the following Dockerfile to get .NetCore 2 installed into the Jenkins container. You can obviously take this further and install the needed plugins and additional software as needed. I hope this helps you out!
FROM jenkins/jenkins:lts
# Switch to root to install .NET Core SDK
USER root
# Just for my sanity... Show me this distro information!
RUN uname -a && cat /etc/*release
# Based on instructiions at https://learn.microsoft.com/en-us/dotnet/core/linux-prerequisites?tabs=netcore2x
# Install depency for dotnet core 2.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl libunwind8 gettext apt-transport-https && \
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg && \
mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg && \
sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/dotnetdev.list' && \
apt-get update
# Install the .Net Core framework, set the path, and show the version of core installed.
RUN apt-get install -y dotnet-sdk-2.0.0 && \
export PATH=$PATH:$HOME/dotnet && \
dotnet --version
# Good idea to switch back to the jenkins user.
USER jenkins
You can run these commands inside the Docker container in order to install .NET Core. They can also be stored in a Dockerfile (as per #Zooly57)
Install the latest .NET Core 2.0:
sudo apt install libunwind8 gettext apt-transport-https
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 2.0
Or LTS version of .NET Core
sudo apt install libunwind8 gettext apt-transport-https
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel LTS
Contents of the script here:
https://github.com/dotnet/cli/blob/master/scripts/obtain/dotnet-install.sh
Fantastic answer by Dennis, it's exactly what I ended up doing. It was a nice introduction to Docker as well :-)
Here's my Dockerfile for Jenkins 2.249.2 (LTS at the time of writing) on Debian 9 (stretch):
# Extend Jenkins 2.249.2 on Debian 9 (stretch)
FROM jenkins/jenkins:2.249.2-lts
# Switch to root user to install .NET SDK
USER root
# Print kernel and distro info
RUN echo "Distro info:" && uname -a && cat /etc/*release
# Install needed tools and upgrade installed packages
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl apt-transport-https software-properties-common \
&& apt-get upgrade -y
# Add Microsoft repository for .NET SDK
RUN curl -sSL https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN apt-add-repository https://packages.microsoft.com/debian/9/prod/
# Install .NET SDK
RUN apt-get update \
&& apt-get install -y dotnet-sdk-3.1
# Switch back to jenkins user
USER jenkins
The dotnet command worked without setting any paths.
I guess when a newer version of Jenkins is released that uses Debian 10, I'll just update the FROM line then the Microsoft repository URL.
I believe you should follow below approach instead:
Develop your asp.net core app and check in to Git(Any source control)
Have a build server which has Jenkins, .Net Core, Docker installed
Configure Jenkins to communicate with Git (webhook/polling - to see if there is a check in)
And configure a Jenkins job which will do the following
Pull the latest from Git,
Restore,
Build,
Publish the asp.net core application,
Create a docker image which has a capability to run the asp.net core app in it
Upload the docker image just created to your Docker Hub
You may not want to do it exactly as mentioned above especially the source control part. But this approach works well.
I have followed this link while I made the above setup.
Hope it helps. Thanks!
For anyone who is struggling with this topic recently, this is what I added to the bottom of my Dockerfile to install the .NET SDK;
USER root
# Install dependencies
RUN apt-get install wget
RUN wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN rm packages-microsoft-prod.deb
# Install .NET SDK 6.0
RUN apt-get update;
RUN apt-get install -y apt-transport-https
RUN apt-get update
RUN apt-get install -y dotnet-sdk-6.0
RUN dotnet --version
This is based on installing the SDK on Ubuntu 18.04 as this is the version that AKS uses which was perfect for my scenario
https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#dependencies

Docker commands require keyboard interaction

I'm trying to create a Docker image for ripping CDs (using abcde).
Here's the relevant portion of the Dockerfile:
FROM ubuntu:17.10
MAINTAINER Graham Nicholls <graham#rockcons.co.uk>
RUN apt update && apt -y install eject vim ruby abcde
...
Unfortunately, the package "abcde" pulls in a mail client (not sure which), and apt tries to configure that by asking what type of mail connection to configure (smarthost/relay etc).
When docker runs, it's not appearing to read from stdin, so I can't redirect into the docker process.
I've tried using --nodeps with apt (and replacing apt with apt-get); unfortunately --nodeps seems no-longer to be a supported option and returns:
E: Command line option --nodeps is not understood in combination with the other options
Someone has suggested using expect in response to a similar question, which I'd rather avoid. This seems to be a "difficult to google" problem - I can't find anything.
So, is there a way of passing in the answer to the config in apt, or of preventing apt from pulling in a mail client, which would be better - I'm not planning in sending updates to cddb.
The typical template to install apt packages in a docker container looks like:
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
eject \
vim \
ruby \
abcde \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
Running it with the "noninteractive" value removes any prompts. You don't want to set that as an ENV since that would also impact any interactive commands you run inside the container.
You also want to cleanup the package database when finished to reduce the layer size and avoid reusing a stale cached package database in a later step.
The no-install-recommends option will reduce the number of packages installed by only installing the required dependencies, not the additional recommended packages. This cuts the size of the root filesystem down by half for me.
If you need to pass a non-default configuration to a package, then use debconf. First run you install somewhere interactively and enter the options you want to save. Install debconf-utils. Then run:
debconf-get-selections | grep "${package_name}"
to view all the options you configured for that package. You can then pipe these options to debconf-set-selections in your container before running your install, e.g.:
RUN echo "postfix postfix/main_mailer_type select No configuration" \
| debconf-set-selections \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
....
or save your selections to a file that you copy in:
COPY debconf-selections /
RUN debconf-set-selections </debconf-selections \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
....

Resources