Making sense out of docker create command line arguments - docker

I am trying to understand the following docker create command from the book Docker in Action 2nd Edition:
docker container create --name export-test dockerinaction/ch7_packed:latest ./echo For Export
Here we are creating a container named export-test that will be used to run the image dockerinaction/ch7_packed:latest. So far so good.
What does the ./echo For Export part in the above command do?
The online documentation for docker create does not yield any clue to me.

It specifies the command that will get run when you eventually docker start the container. It overrides the CMD in the image's Dockerfile. If the image has an ENTRYPOINT then the command will be passed to the entrypoint command as command-line arguments.

Related

ENTRYPOINT without docker run

I have an executable that's containerized and I use the entry point statement in the Dockerfile:
ENTRYPOINT ["s10cmd"]
However, this is a statistical app that needs to receive a data file, so I cannot use docker run. Instead I create the container using docker create and then docker cp to copy the dat file into the container. However, none of the docker commands except run allow me to call the container as an executable.
Should I in this case, not specify ENTRYPOINT or CMD, and just do docker start, docker exec s10cmd /tmp/data.dat?
Docker images are just like templates , and Docker containers are live running machines.
In order to execute any commands - it requires a container , so you need to create a container , when you start the container, your entry-point will launch the command and then container will close automatically.
#>docker create <-- This will create an instance of the docker image
#>docker cp <-- Copy the relevant file into the container
#>docker start <-- Start the container entrypoint will do rest of the job.

Dockerfile overwriting file in container

I know this is written sloppy but I'm new to Docker and just trying to get the hang of it. I'm pulling an image FROM wordpress:4.9.2-php7.2-apache
Im then attempting to overwrite the deflate.conf file from inside my Dockerfile. The command I'm using is as follows.
ADD /deflate.conf ../../../etc/apache2/mods-available/
Using this command the image builds properly but as soon as I run it the container immediately fails?
When I comment out the ADD line, and build/run the image the container runs fine. So I attempted the copy command from the command line like so:
docker cp deflate.conf <name>:../../../etc/apache2/mods-available/deflate.conf
Using this command everything is fine, and I get the desired result.
Im not sure why my Dockerfile won't work but the command line does.
Any help would greatly appreciated.
Why not use COPY or ADD with the absolute path. Instead of using ../../../etc/apache2/mods-available/deflate.conf, the format should be:
COPY /deflate.conf /etc/apache2/mods-available/deflate.conf
You can also use Docker volumes for this. Ignore the COPY during docker build, then with your run command, include -v option:
$ docker run -v /deflate.conf:/etc/apache2/mods-available/deflate.conf -d -p 80:80 test
This should also do the trick. Please note that the modules on /etc/apache2/mods-available/ are not loaded by default when apache service starts, active modules should be copied to /etc/apache2/mods-enabled/.
I think same result as the command line you can achieve with:
COPY /deflate.conf ../../../etc/apache2/mods-available/deflate.conf
in your Dockerfile.

How to override default docker container command or revert to previous container state?

I have a docker image running a wordpress installation. The image by executes the apache server as default command. So when you stop the apache service the container exits.
The problem comes after messing up the apache server config. The container cannot start and I cannot recover the image contents.
My options are to either override the command that the container runs or revert last file system changes to a previous state.
Is any of these things possible? Alternatives?
When you start a container with docker run, you can provide a command to run inside the container. This will override any command specified in the image. For example:
docker run -it some/container bash
If you have modified the configuration inside the container, it would not affect the content of the image. So you can "revert the filesystem changes" just by starting a new container from the original image...in which case you still have the original image available.
The only way to that changes inside a container affect an image are if you use the docker commit command to generate a new image containing the changes you made in the container.
If you just want to copy the contents out you can use the command below with a more specific path.
sudo docker cp containername:/var/ /varbackup/
https://docs.docker.com/reference/commandline/cli/#cp
The file system is also accessible from the host. Run the command below and in the volumes section at the bottom it should have a path to where your file system modifications are stored. This is not a good permanent solution.
docker inspect containername
If you re-create the container later you should look into keeping your data outside of the container and linking it into the container as a virtual path when you create the container. If you link your apache config file into the container this way you can edit it while the container is not running
Managing Data in Containers
http://docs.docker.com/userguide/dockervolumes/
Edit 1: Not suggesting this as a best practice but it should work.
This should display the path to the apache2.conf on the host.
Replace some-wordpress with your container name.
CONTAINER_ID=$(docker inspect -f '{{.Id}}' some-wordpress)
sudo find /var/lib/docker/ -name apache2.conf | grep $CONTAINER_ID
There are different ways of overriding the default command of a docker image. Here you have two:
If you have an image with a default CMD command, you can simply override it in docker run giving as last argument the command (with its argument) you wish to run (Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...])
Create a wrapper image with BASE image the one you want to override the CMD or ENTRYPOINT. Example
FROM my_image
CMD ["my-new-cmd"]
Also, you can try to revert the changes in different ways:
If you have the Dockerfile of the image you want to revert, simple rewrite the changes into Dockerfile and run again docker build process.
If you don't have the Dockerfile and you built the image committing the changes, you can use docker history <IMAGE_NAME>:tag, locate the IMAGE_ID of the commit you want, and run that commit or tag that commit with the name (and tag) you wish (using -f option if you are overriding a tag name). Example:
$ docker history docker_io_package:latest
$ docker tag -f c7b38f258a80 docker_io_package:latest
If it requires starting a command with a set of arguments, for example
ls -al /bin
try to make it like that
docker run --entrypoint ls -it debian /bin -al
where ls goes after --entrypoint and all arguments are placed after the image name

Run commands on create a new Docker container

Is it possible to add instructions like RUN in Dockerfile that, instead of run on docker build command, execute when a new container is created with docker run? I think this can be useful to initialize a volume attached to host file system.
Take a look at the ENTRYPOINT command. This specifies a command to run when the container starts, regardless of what someone provides as a command on the docker run command line. In fact, it is the job of the ENTRYPOINT script to interpret any command passed to docker run.
I think you are looking for the CMD
https://docs.docker.com/reference/builder/#cmd
The main purpose of a CMD is to provide defaults for an executing
container. These defaults can include an executable, or they can omit
the executable, in which case you must specify an ENTRYPOINT
instruction as well.
Note: don't confuse RUN with CMD. RUN actually runs a command and
commits the result; CMD does not execute anything at build time, but
specifies the intended command for the image.
You should also look into using Data Containers see this excellent Blog post.
Persistent volumes with Docker - Data-only container pattern
http://container42.com/2013/12/16/persistent-volumes-with-docker-container-as-volume-pattern/

docker running a data container from scratch

I created a data only container containing static HTML files that are intended to be consumed by a nginx container. Goal is that my webapp is providing a volume that nginx can use.
For this reason I created a simple Dockerfile:
FROM scratch
MAINTAINER me <me#me.com>
ADD dist/ /webappp/
When I run the created container from command line run -d -v /webappp --name webapp myOrg/webapp echo yo
I get the error Error response from daemon: Cannot start container db7fd5cd40d76311f8776b1710b4fe6d66284fe75253a806e281cd8ae5169637: exec: "echo": executable file not found in $PATH which if of course correct because the image has no commands at all the can be executed. Running a container without a command is not possible.
While this error on command line is not a big problem for me because I know the data container is still created and can now be accessed by nginx it turns out to be a no go if I want to automate it with Vagrant. The automated processes always fail because of this error.
My only solution so far is to extend my little handy image from from a distro which IMHO doesn't make sense for a data only container in order just to call echo or true!
Is there a NOP exec command in docker or does docker need always to execute something, is it possible to run a scratch container that does nothing or does not produce an error.
As mentioned in the Docker manual: The container don't need to be running. It also doesn't say that the container "should" be able to run at all.
So instead of echoing something stupid by running a data only container e.g. docker run -v /webappp --name webapp myOrg/webapp echo yo
It is already enough to just create the container and never run/start it.
docker create -v /webappp --name webapp myOrg/webapp
Note to self: Vagrant does not support docker create when provisioning!
Why are you using scratch?
Just use the nginx image as a base. You already have the image cached so it won't take up any more space and you'll be able to call echo.
Some references for data containers:
Data-only container madness
Understanding Volumes in Docker
Offiical docs on data containers

Resources