How to make sure commands are not repeated in docker - docker

I am learning about build image using docker file.
short description of what I have done
step 1
For making testing I have started on build image using below docker file
FROM centos:6.8
MAINTAINER Bilal Usean "xxxxx#xxx.xxx"
RUN yum install -y httpd; yum -y clean all
after that I have run the below command
docker build -t httpd/centos:6.8 .
it is successfully install apache in httpd/centos:6.8 image
step 2
Next I am trying to install jdk in the same existing newly created image
FROM centos:6.8
MAINTAINER Bilal Usean "xxxxxx#xxx#xx"
RUN yum install -y httpd; yum -y clean all
yum install java-1.6.0-openjdk-devel; yum -y clean all
after that I have run the below command
docker build -t httpd/centos:6.8 .
But It will start from again httpd install, I expected it will skip that httpd step for already install.
I think it is not a good practice to make docker file.I have 20 RUN command in docker file, that is download heavy size file from net so I want to make sure about it each command success. otherwise it will fail intermediately and again it will charge more MB.
note: If I am in the wrong way, please describe the best way to deal with image and docker file.

It repeats here because you did not add another RUN command, but appended (and changed) the previous command (docker detects this change, and runs the new command).
What you should be writing is:
FROM centos:6.8
MAINTAINER Bilal Usean "xxxxxxxx#xxx.xxx"
RUN yum install -y httpd; yum -y clean all
RUN yum install java-1.6.0-openjdk-devel; yum -y clean all

Related

Couldn't find an alternative telinit implementation to spawn in DOCKER while starting MarkLogic application in CENTOS7

I am running a docker file in windows 11 which will do two operations by running two scripts parallelly. So there are 2 bash scripts to do these 2 operations-
Install an application MarkLogic in CentOS7 (marklogicinstall.sh)
Deploy some files in the application server (deploy.sh)
I have written a wrapper script which commands to first run the script1, then the second1
However, I get this below error where the first script ends and before the second one starts-
Couldn't find an alternative telinit implementation to spawn.
The installation script which is marklogicinstall.sh is like this -
#!/bin/bash
# Get any CentOS updates then clear the Docker cache
#install yum by rpm
#yum -y update && yum clean all
# Install MarkLogic dependencies
yum -y install glibc.i686 gdb.x86_64 redhat-lsb.x86_64 && yum clean all
# Install the initscripts package so MarkLogic starts ok
yum -y install initscripts && yum clean all
# Install MarkLogic then delete the .RPM file if the install succeeded
yum -y install MarkLogic.rpm && rm MarkLogic.rpm
printf "Marklogic installation done"
# Set the Path
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/MarkLogic/mlcmd/bin"
exec /usr/sbin/init
service /etc/init.d/MarkLogic start
Is it a problem with the start command?

Temporarily cache RUN apt-get update && apt-get install in Dockerfile

Is it possible to temporarily cache this line RUN apt-get update && apt-get install -y in Dockerfile?
Reason is when troubleshooting Dockerfile, I rebuild the image several times and this line has the longest wait time.
Yes, it possible.
Create docker image from your docker file. Separate file to 2 Dockerfile's, first with FROM and RUN apt-get update && apt-get install -y, second with other instructions
cd /dir/with/Dockerfile
docker image build -t my-fast-docker .
After build use image in second Dockerfile
FROM my-fast-docker:latest

issue in creating docker image from docker file

Created a Docker file in oreder to install Tomcat server from Unix as bashe os
My Dockerfile:
FROM ubuntu
RUN apt-get update && apt-get upgrade -y #to update os
RUN apt-get dist-upgrade
RUN apt-get install build-essential
RUN apt-get install openjdk-8-jdk # to install java 8
RUN apt-get wget -y #to install wget package
RUN apt-get wget https://mirrors.estointernet.in/apache/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz #to download tomcat
RUN tar -xvzf apache-tomcat-9.0.37 # unzipping the tomcat
RUN mkdir tomcat # craeting tomacat directory
RUN cp apache-tomcat-9.0.37/* tomcat # copying tomact files to tomact directory
Command to create Docker Image from Docker file:
docker build -t [img name] -f [file name] .
On execution, while installing java package am getting like this:
'''After this operation, 242 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y'''
You are getting the prompt because the command is awaiting user input for whether or not to install a package. The -y flag you're using for a few of them (like wget) allows bash to assume a yes. Add this flag to all your installation commands.
By the way, there's quite a few potential issues with the Dockerfile you posted.
For example, you have RUN apt-get wget ...
Are you sure that is what you want to do, and not just RUN wget ...? Unless wget is a command that apt-get takes, which it isn't, it will cause unexpected behavior.
You also seem to be missing the command to start the Tomcat server, which can make it so that nothing happens when you attempt to run the image.
I think you should add DEBIAN_FRONTEND=noninteractive when running the apt-get commands, something like this:
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install build-essential -y
Also, it's considered bad practice to use multiple RUN steps which could be consolidated into one. More about Dockerfile best practices can be found here.

How to install multiple packages using apt-get via a Dockerfile

So I am trying to make a basic Dockerfile, but when I run this it says
The command bin/sh -c sudo apt-get install git python-yaml python-jinja2 returned a non-zero code: 1
My question is what am I doing wrong here, and is it even allowed to do commands like 'cd' and 'source' from the Dockerfile?
FROM Ubuntu
MAINTAINER example
#install and source ansible
RUN sudo apt-get update
RUN sudo apt-get install git python-yaml python-jinja2 python-pycurl
RUN sudo git clone https://github.com/ansible/ansible.git
RUN sudo cd ansible
RUN sudo source ./hacking/env-setup
Couple of pointers / comments here:
It's ubuntu not Ubuntu
From base ubuntu (and unfortunately, a lot of images) you don't need to use sudo, the default user is root (and in ubuntu, sudo is not included anyway)
You want your apt-get update and apt-get install to be RUN as part of the same command, to prevent issues with Docker's layer cache
You need to use the -y flag to apt-get install as the Docker build process runs non-interactively
Few other points I could make about clearing up your apt-cache and other non-required artifacts after running the commands, but this should be enough to get going on
New Dockerfile (taking into account the above) would look something like:
FROM ubuntu
MAINTAINER example
#install and source ansible
RUN apt-get update && apt-get install -y \
git \
python-yaml \
python-jinja2 \
python-pycurl
RUN git clone https://github.com/ansible/ansible.git
WORKDIR ansible/hacking
RUN chmod +x env-setup; sync \
&& ./env-setup
You might also find it useful to read the Dockerfile best practises.
Edit: Larsks answer also makes some useful points about the state of the container not persisting between layers so you should go upvote him too!
When building an image you're already running as root. You don't need sudo and there's a good chance it's not installed.
Along similar lines, this will never work:
RUN sudo cd ansible
The cd command only affects the current process; this would run cd and then exit, leaving you in the same directory you started in. The Docker WORKDIR directive can be used to persistently change the working directory:
WORKDIR ansible
You can also pass a series of shell commands to the RUN directive, like this:
RUN cd ansible; source ./hacking/env-setup
But even that probably won't do what you want, because like the sudo cd ... command earlier, that would modify your environment...and then exit, leaving the current environment unchanged in any subsequent commands.
If you want to run Ansible in a container, you should probably either install it, or plan to run the env-setup script manually after starting a container from the image.

How can I docker-build with Dockerfile?

I building docker image. But it does not success.
/Users/username/.vim exists on my host os, But it does not success.
How I can success docker- build?
Error Message:
Step 16 : ADD /Users/username/.vim/ /root/.vim
lstat Users/username/.vim/: no such file or directory
The following is my Dockerfile.
Dockerfile:
FROM ubuntu:latest
MAINTAINER MyName
RUN /bin/bash
RUN mkdir ~/cworks
RUN mkdir ~/pyworks
RUN apt-get -y update
RUN apt-get -y install curl
RUN apt-get -y install clang
RUN apt-get -y install man
RUN apt-get -y install vim
RUN apt-get -y install python3
RUN apt-get -y install git
RUN apt-get -y install make
RUN apt-get -y upgrade
RUN curl -kL https://bootstrap.pypa.io/get-pip.py | python3
ADD /Users/username/.vim/ /root/.vim
ADD /Users/username/.vimrc /root/.vimrc
Platform: OS X 10.11.4
You cannot execute ADD (or COPY) on a file that is not inside the directory that contains your Dockerfile.
The reason for that is that building docker images is meant to be a deterministic build. If I build the Dockerimage on my computer with your Dockerfile, I would have a different .vim
The docker team impose this limitation to encourage people using a self contained directory with a Dockerfile, and any file to add to it.
In your case, you will need to copy the file in the same directory of the Dockerfile first, and run:
ADD .vim /root/.vim
Or arguably better:
COPY .vim /root/.vim
Use this form instead. It works with hidden files(dot files) and filename contains whitespaces.
ADD ["/Users/username/.vim/", "/root/.vim"]
https://docs.docker.com/engine/reference/builder/#/add
Please remove tailing slash after .vim
So, it will go as
ADD /Users/username/.vim /root/.vim

Resources