Building a docker image differently for test and release - docker

We have a tool we build into a docker image to run via Wine.
For testing the last line of our Dockerfile runs the application like this:
# Run application
ENTRYPOINT ["wine", "/app/OurApp.exe"]
This allows us to run test data thru it via:
echo %TEST_JSON% | docker run -i -a stdin -a stdout OurApp
For deployment the docker image is wrapped into a larger image that then runs the app. In order for it to work correctly when deployed I have to comment out the ENTRYPOINT line from the Dockerfile.
I'm not very familiar with Docker (I inherited this project) but assume their might be a better way to deal with Test / Deploy configurations. What would you suggest?

Related

How to test a Dockerfile with minimal overhead

I'm trying to learn how to write a Dockerfile. Currently my strategy is as follows:
Guess what commands are correct to write based documentation.
Run sudo docker-compose up --build -d to build a docker container
Wait ~5 minutes for my anaconda packages to install
Find that I made a mistake on step 15, and go back to step 1.
Is there a way to interactively enter the commands for a Dockerfile, or to cache the first 14 successful steps so I don't need to rebuild the entire file? I saw something about docker exec but it seems that's only for running containers. I also want to try and use the same syntax as I use in the dockerfile (i.e. ENTRYPOINT and ENV) since I'm not sure what the bash equivalent is/if it exists.
you can run docker-compose without the --build flag that way you don't have to rebuild the image every time, although as you are testing the Dockerfile i don't know if you have much options here; the docker should cache automatically the builds but only if there's no changes from the last time that you made a build, and there's no way to build a image interactively, docker doesn't work like that, lastly, the docker exec is just to run commands inside the container that was created from the build.
some references for you: docker cache, docker file best practices

Can I tell a dockerfile to write a file to the host?

I am trying to use docker to build my project in a specific environment, but I am wondering if there's a way to avoid having to docker run -v [mypath]:[workdir] -it [name] to simply get some files out.
Can I tell a dockerfile to run some commands and then copy the resulting files to the host?
No, images and containers are intentionally isolated from the host's filesystem, and there's intentionally no way for an image to read or write files on the host without being explicitly granted the privilege in a docker run -v option.
If your real goal is to run something to interact with files on the host then you'll often be better off installing and running it directly on the host than writing the very long docker run command line (and needing root privileges to do anything).
You can't write file directly to you host system. But you can still achieve that by printing your result into console, and the write it directly to your file.
Take an example of this docker image: docker/whalesay. when you run docker run docker/whalesay cowsay Hello there!, It will print into console the text Hello there! and the whale together. So you can write these thing back to your file by doing:
docker run docker/whalesay cowsay Hello there! | tee ./somefiletowrite.txt

Debugging docker-compose build that freezes on building first service

I have been following a tutorial on how to deploy docker containers to AWS, which I have managed to do successfully. However now that I have modified a flask web app with my own code/logic, it never completes building the first service.
My last command:
docker-compose -f docker-compose-prod.yml up -d --build
It stars to say:
Building feapi
Then nothing happens, sometimes I get:
ERROR: SSL error: ('The write operation timed out',)
How can I debug this or at least see what is happening behind the scene, as I am not sure what is causing the error? I know docker-compose offers logs but not sure how to implement it and if its necessary.
Sometimes your context contains too many files.
When the docker build starts, it collects all the files which is in your project folder/context dir, except if you mention them in the .dockerignore.
If you have GBs of files around, it can collect it for minutes and the resulting image size will be huge.
In the official docs (https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) see this paragraph:
"Omitting the build context can be useful in situations where your Dockerfile does not require files to be copied into the image, and improves the build-speed, as no files are sent to the daemon."
If you are uncertain about the size of your build context, you could run a simple docker build, which prints the context size it finds. Eg.:
> docker build -t check-context:latest .
Sending build context to Docker daemon 1.086MB
...
docker-composer --build does docker build for you.
If you run manually the docker build command, you will have the output of the build.
Then, docker build just runs the commmands of your Dockerfile this is up to you to put your Dockerfile commands in verbose / debug mode.

is it possible to wrap an entire ubuntu 14 os in a docker image

I have a Ubuntu 14 desktop, on which I do some of my development work.
This work mainly revolves around Django & Flask development using PyCharm
I was wandering if it was possible to wrap the entire OS file system in a Docker container, so my whole development environment, including PyCharm and any other tools, would become portable
Yes, this is where Docker shines. Once you install Docker you can run:
docker run --name my-dev -it ubuntu:14.04 /bin/bash
and this will put you, as root, inside a Docker container's bash prompt. It is for all intents and purposes the entire os without anything extra, you will need to install the extras, like pycharm, flask, django, etc. Your entire environment. The environment you start with has nothing, so you will have to add things like pip (apt-get install -y python-pip), and other goodies. Once you have your entire environment you can exit (with exit, or ^D) and you will be back in your host operating system. Then you can commit :
docker commit -m 'this is my development image' my-dev my-dev
This takes the Docker image you just ran (and updated with changes) and saves it on your machine with the tag my-dev:v1, any time in the future you can run this again using the invocation:
docker run -it my-dev /bin/bash
Building a Docker image like this is harder, it is easier once you learn how to make a Dockerfile that describes the base image (ubuntu:14.04) and all of the modifications you want to make to it in a file called Dockerfile. I have an example of a Dockerfile here:
https://github.com/tacodata/pythondev
This builds my python development environment, including git, ssh keys, compilers, etc. It does have my name hardcoded in it, so, it won't help you much doing development (I need to fix that). Anyway, you can download the Dockerfile, change it with your details in it, and create your own image like this:
docker build -t my-dev -< Dockerfile
There are hundreds of examples on the Docker hub which is where I started with mine.
-g

Copy a file from container to host during build process

How do I copy files from a docker container to the host machine during docker build command?
As a part of building my docker image for my app, I'm running some tests inside it, and I would like to copy the output of the test run into the host (which is a continuous integration server) to do some reporting.
I wouldn't run the tests during build, this will only increase the size of your image. I would recommend you to build the image and then run it mounting a host volume into the container and changing the working directory to the mount point.
docker run -v `pwd`/results:/results -w /results -t IMAGE test_script
There is no easy way to do this. Volumes are only created at run time. You can grab it out of the docker filesystem, (e.g. mine is /var/lib/docker/devicemapper/mnt/CONTAINER_ID/rootfs/PATH_TO_FILE) though there is no good way to figure out when your test process is complete. You could create a file when it's finished and do an inotify, but this is ugly.

Resources