How to run custom Docker file? - docker

So here is a very cool Docker file.
To run it, I do:
wget https://cran.r-project.org/src/contrib/FastRCS_0.0.7.tar.gz
tar -xvzf FastRCS_0.0.7.tar.gz
docker run --rm -ti -v $(pwd):/mnt rocker/r-devel-ubsan-clang check.r --setwd /mnt -a --install-deps FastRCS_0.0.7.tar.gz
But now suppose I want to save this DockerFile and run the saved version from the current directory (i.e. not just the one on github).
How can I do this?
The idea is that I need to customize this DockerFile a bit and run the customized version.

Sounds like you want to download the raw file from https://raw.githubusercontent.com/rocker-org/r-devel-san-clang/master/Dockerfile
and save it into a file named Dockerfile
Then you could edit the file to make your changes, and then just build your image with docker build . when you are in the Dockerfile directory

This is a basic Docker usage question--look into docker commit.
You may want to study one of the many fine Docker tutorials out there.

Related

How does to download and extract .tar files in a container for Dockerfile?

Over here is a use case - I want to download and extract all files from a particular website and allow users to specify from which workweek it might be done. Please, imagine using one docker command and specifying only the variable which tells where to go, download and extract files.
The problem is I want to allow a user to manipulate variables that refer to a particular workweek.
Now it is only my idea, not sure If I am thinking right before I start to design my Dockerfile.
Dockerfile:
...
ENV TARGET="$WW_DIR"
...
Now you can imagine that the first user wants to download files from WW17 so he can type:
docker container run -e TARGET=WW17 <image_name>
The second one wants to download files from WW25:
docker container run -e TARGET=WW25 <image_name>
Etc.
Underhood Dockerfile knows that it must go to the directory from WW17 (in the first scenario) or WW25 (in the second scenario). My imagination is that a new container is created then using for example "curl" files are downloaded from an external server and extracted.
Can you recommend to me the best methods with some examples of how to solve it? Apply bash script inside of the container?
Thanks.
There is no Dockerfile at docker container run, it just runs the command. So write a command that does what you want or add the data to the image when building it with Dockerfile.
# Dockerfile
FROM your_favourite_image
COPY your_script /
RUN chmod +x /your_script
CMD /your_script
# your_script
#!/usr/bin/env your_favourite_langauge_like_python_or_bash_or_perl
# download the $TARGET or whatever you want to do
And then
docker build -t image .
docker run -r TARGET=WW1 image
Reading: https://docs.docker.com/engine/reference/builder/#cmd https://docs.docker.com/engine/reference/builder/#entrypoint https://docs.docker.com/get-started/overview/ https://btholt.github.io/complete-intro-to-containers/dockerfile

How can I reproduce docker commands seen in docker hub image layers?

I am wondering how it is possible to reproduce the docker commands seen in this docker image. The image copies certain versions of clang and gcc, which is something I wish to do in my own dockerfile. I cannot use the linked docker image, as it contains many commands that are unnecessary for the work I want to do.
The very first command is
ADD file:2cddee716e84c40540a69c48051bd2dcf6cd3bd02a3e399334e97f20a77126ff in /
Further down, there are many similar COPY commands. I wish to reproduce the following command in my own dockerfile:
COPY dir:49371ba683da700cabfad7284da39bd2144aa0c46086c3015a74737d7be6b51e in /compilers/clang/3.4.2
The command copies clang-3.4.2 into the given folder. I am unsure how I can do the same, or even what the hash is/means.
I tried looking, but I couldn't find the Dockerfile used to create the image. There is another way though.
It's quite a large image and I'm on a terrible internet connection, so I haven't tested this myself, but one thing you can do is copy the things you need from the image into a new one of your own like this
FROM cnsun/perses:perses_part_54_name_clang_trunk AS original
FROM ubuntu:latest
COPY --from=original /compilers/clang/3.4.2 /compilers/clang/3.4.2
You can also copy the files from the image to your computer. Then you can copy them from there into new images without referencing the cnsun image:
docker run --rm -v $(pwd):/dest --entrypoint /bin/bash cnsun/perses:perses_part_54_name_clang_trunk -c "cp -r /compilers/clang/3.4.2 /dest"
This will copy the /compilers/clang/3.4.2 directory into the current directory on the host. If your host is Windows, replace $(pwd) with %cd%.

Creating my first docker image with a local zip

very new to Docker here. I am trying to use a maven 2.1.0 zip to create a docker image.
my
dockerfile.docker file is :
# syntax=docker/dockerfile:1
FROM scratch
LABEL maintainer="Myname"
LABEL maintainer="myemail"
RUN wget HTTP://archive.apache.org/dist/maven/binaries/apache-maven-2.1.0-bin.zip
RUN unzip
I am not exactly sure if I am doing this right
docker build -t apache-maven:2.1.0 .
Essentially I just wanted to create this image locally so I could then push it out to my targeted endpoint. Any help realizing what I did wrong would be appreciated. Whenever I run this build command it tells me it failed to read the dockerfile and that there's no such file or directory.
By default, it will try to find the file with the exact name Dockerfile.
If for any reason, you want to have a different file name like your scenario, you should use next:
docker build -f dockerfile.docker -t apache-maven:2.1.0 .
Detail refers to Specify a Dockerfile (-f)

Sending docker build contexts

My directory structure is as follows
cassandra
Dockerfile
downloads
225M file
I am inside cassandra directory. My build command is
docker build -t image_cassandra .
I know that it will send all the contents in . current directory. So it takes so much of time to send this 225M file. I need this file in my Dockerfile.
Add downloads/ /tmp/
I want to avoid this much of delay. And I know that, we cannot use ../ in docker ADD command. So is there any way to reduce the size of build context and have this ADD command.
This file is not part of web. So i cannot use any apt-get wget statements. Or isn't possible?
You could separate the project into two docker images, a big one that changes infrequently, and a small one that you can change fast.
Project1/
Dockerfile
bigfile
Project2/
Dockerfile
Project1/Dockerfile would look like this:
FROM ubuntu
RUN apt-get install cassandra
ADD bigfile
Then if you build it and tag it with docker build -t project1 Project1, you can use the result in Project2/Dockerfile:
FROM project1
RUN fast configuration commands

How can I make a host directory mount with the container directory's contents?

What I am trying to do is set up a docker container for ghost where I can easily modify the theme and other content. So I am making /opt/ghost/content a volume and mounting that on the host.
It looks like I will have to manually copy the theme into the host directory because when I mount it, it is an empty directory. So my content directory is totally empty. I am pretty sure I am doing something wrong.
I have tried a few different variations including using ADD with default themes folder, putting VOLUME at the end of the Dockerfile. I keep ending up with an empty content directory.
Does anyone have a Dockerfile doing something similar that is already working that I can look at?
Or maybe I can use the docker cp command somehow to populate the volume?
I may be missing something obvious or have made a silly mistake in my attempts to achieve this. But the basic thing is I want to be able to upload a new set of files into the ghost themes directory using a host-mounted volume and also have the casper theme in there by default.
This is what I have in my Dockerfile right now:
FROM ubuntu:12.04
MAINTAINER Jason Livesay "ithkuil#gmail.com"
RUN apt-get install -y python-software-properties
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get -qq update
RUN apt-get install -y sudo curl unzip nodejs=0.10.20-1chl1~precise1
RUN curl -L https://en.ghost.org/zip/ghost-0.3.2.zip > /tmp/ghost.zip
RUN useradd ghost
RUN mkdir -p /opt/ghost
WORKDIR /opt/ghost
RUN unzip /tmp/ghost.zip
RUN npm install --production
# Volumes
RUN mkdir /data
ADD run /usr/local/bin/run
ADD config.js /opt/ghost/config.js
ADD content /opt/ghost/content/
RUN chown -R ghost:ghost /opt/ghost
ENV NODE_ENV production
ENV GHOST_URL http://my-ghost-blog.com
EXPOSE 2368
CMD ["/usr/local/bin/run"]
VOLUME ["/data", "/opt/ghost/content"]
As far as I know, empty host-mounted (bound) volumes still will not receive contents of directories set up during the build, BUT data containers referenced with --volumes-from WILL.
So now I think the answer is, rather than writing code to work around non-initialized host-mounted volumes, forget host-mounted volumes and instead use data containers.
Data containers use the same image as the one you are trying to persist data for (so they have the same directories etc.).
docker run -d --name myapp_data mystuff/myapp echo Data container for myapp
Note that it will run and then exit, so your data containers for volumes won't stay running. If you want to keep them running you can use something like sleep infinity instead of echo, although this will obviously take more resources and isn't necessary or useful unless you have some specific reason -- like assuming that all of your relevant containers are still running.
You then use --volumes-from to use the directories from the data container:
docker run -d --name myapp --volumes-from myapp_data
https://docs.docker.com/userguide/dockervolumes/
You need to place the VOLUME directive before actually adding content to it.
My answer is completely wrong! Look here it seems there is actually a bug. If the VOLUME command happens after the directory already exists in the container, then changes are not persisted.
The Dockerfile should always end with a CMD or an ENTRYPOINT.
UPDATE
My solution would be to ADD files in the container home directory, then use a shell script as an entry point in which I'll copy the file in the shared volume and do all the other tasks.
I've been looking into the same thing. The problem I encountered was that I was using a relative local mount path, something like:
docker run -i -t -v ../data:/opt/data image
Switching to an absolute local path fixed this up for me:
docker run -i -t -v /path/to/my/data:/opt/data image
Can you confirm whether you were doing a relative path, and whether this helps?
Docker V1.8.1 preserves data in a volume if you mount it with the run command. From the docker docs:
Volumes are initialized when a container is created. If the container’s
base image contains data at the specified mount point, that existing
data is copied into the new volume upon volume initialization.
Example: An image defines the
/var/www/html
as a volume and populates it with the data of a web application. Your docker hosts provides a mount directory
/my/host/dir
You start the image by
docker run -v /my/host/dir:/var/www/html image
then you will get all the data from /var/www/html in the hosts /my/host/dir
This data will persist even if you delete the container or the image.

Resources