Add extra_hosts to docker file - docker

I have a docker image which is based off node:12. This image, along with others, are brought up via a docker-composer.yml file. The issue I am having is that I am unable to add extra_hosts to the container. In my yml file - I've got the following
my-app:
image: <image_name>
container_name: <container_name>
extra_hosts:
- "somehost:162.242.195.82"
This appears to work with other containers but not ones based of node:12. Is this functionality not available to images based off node:12? Or am I doing something wrong?

Check the base image of the node:12, you have other choices (Stretch, Alpine, Buster) https://hub.docker.com/_/node/
It is a very bad idea to alter the /etc/hosts of an image manually and to build a new image with an altered /etc/hosts containing specific infos.

Potential workaround:
Create a Dockerfile which uses node:12 as your parent image and then write your host into the /etc/hosts manually. Then update your compose setup to build from that Dockerfile.
As mentioned below, this is purely a hacky workaround. It may be worth trying the other node:12 distribution such as node:12-alpine.

Related

entry point of docker container dependent on local file system and not in the image

I am working on a docker container that is being created from a generic image. The entry point of this container is dependent on a file in the local file system and not in the generic image. My docker-compose file looks something like this:
service_name:
image: base_generic_image
container_name: container_name
entrypoint:
- "/user/dlc/bin"
- "-p"
- "localFolder/fileName.ext"
- more parameters
The challenge that I am facing is removing this dependency and adding it to the base_generic_image at run time so that I can deploy it independently. Should I add this file to the base generic image and then proceed(this file is not required by others) or should this be done when creating the container, if so then what is the best way of going about it.
You should create a separate image for each part of your application. These can be based on the base image if you'd like; the Dockerfile might look like
FROM base_generic_image
COPY dlc /usr/bin
CMD ["dlc"]
Your Docker Compose setup might have a subdirectory for each component and could look like
servicename:
image: my/servicename
build:
context: ./servicename
command: ["dlc", "-p", ...]
In general Docker volumes and bind-mounts are good things to use for persistent data (when absolutely required; stateless containers with external databases are often easier to manage), getting log files out of containers, and pushing complex configuration into containers. The actual program that's being run generally should be built into the base image. The goal is that you can take the image and docker run it on a clean system without any of your development environment on it.

Why use label in docker-compose.yml, can't environment do the job?

I am learning docker now. I am trying to figure out what kind of problem Docker label can solve.
I can understand why use label in Dockerfile, e.g add build-related metadata, but I still don't get why using it in docker-compose.yml? What is the difference between using labels vs environment? I assume there will be different use cases but I just can't figure it out.
Can someone give me some practical example?
Thanks
docker-compose.yml is used by docker-compose utility to build and run the services which you have defined in docker-compose.yml
While working with docker-compose we can use two thing
docker-compose build this will build the services which is defined under docker-compose.yml but in order to run this services it has to have a image which is with docker-engine if you do docker image ls you find the images which is built up with the docker-compose and inspect it there you find a label which defines the metadata of that particular image.
docker-compose up this will run the services which is built up in docker-container build now this running container has to have some metadata like env this is set with enviroment in docker-compose.yml
P.S. :- This is my first answer in stack overflow. If you didn't get just give a comment I will try to explain my best.
Another reason to use labels in docker-compose is to flag your containers as part of this docker-compose suite of containers, as opposed to other purposes each docker image might get used for.
Here's an example docker-compose.yml that shares labels across two services:
x-common-labels: &common-labels
my.project.environment: "my project"
my.project.maintainer: "me#example.com"
services:
s1:
image: somebodyelse/someimage
labels:
<<: *common-labels
# ...
s2:
build:
context: .
image: my/s2
labels:
<<: *common-labels
# ...
Then you can do things like this to just kill this project's containers.
docker rm -f $(docker container ls --format "{{.ID}}" --filter "label=my.project.environment")
re: labels vs. environment variables
Labels are only available to the docker and docker-compose commands on your host.
Environment variables are also available at run-time inside the docker container.
LABEL can be utilized to embed as much metadata as possible about the Docker image, so to make it easier to work with.
Some main purposes of adding LABEL to a Docker image are:
As a documentation.
You can provide author, description, link to a usage instructions etc.
For versioning.
You can ensure that some new features even with the same latest tag will be applicable for certain versions, so might not broke some old existing features.
Any other metadata for programmatic access.
This page provides a guideline and the most common usages of Docker LABEL.

Overriding image version in docker-compose file

I'm working on overriding default docker-compose.yml file using docker-compose.override.yml as shown in this link, And I can able to specify ports and volumes in the override file.
In the similar way, is it also possible to specify version of the image which needs to be deployed? If no, what is the best way to handle such circumstance where we need to specify different version for the image?
Any help on this would be great.
Docker is already having that feature. I tried to override image name with simple docker-compose, it is working.
For example,
docker-compose.yml with content,
my-httpd:
image: httpd:latest
ports:
- "1110:80"
And docker-compose.override.yml with content,
my-httpd:
image: httpd:2.4
After the execution of docker-compose -d, here is the docker ps info,
It uses ports from docker-compose.yml (not overrided) and image from docker-compose.override.yml as it is getting overridden here.
Note: It you have different names and location, you could use it like the following command instead of docker-compose -d,
docker-compose -f <DOCKER COMPOSE LOCATION> -f <OVERRIDE FILE LOCATION> up -d
Edit 2:
Overriding in the above manner will only replace the non array values and the array variables will be merged.
For example, if I have ports in both files which is an array, it will bind both the ports instead of taking ports value just from the overriding file unlike the image part (non array).
There is (now?) a better option for what you want to do. From
https://docs.docker.com/compose/environment-variables/
It’s possible to use environment variables in your shell to populate values inside a Compose file:
web:
image: "webapp:${TAG}"
For example you need to have 3 versions of docker:
docker-composer-master.yml
docker-composer-dev.yml
docker-composer-docker.yml
You can create 3 file docker-composer and add content as the below picture

Overwrite files with `docker run`

Maybe I'm missing this when reading the docs, but is there a way to overwrite files on the container's file system when issuing a docker run command?
Something akin to the Dockerfile COPY command? The key desire here is to be able to take a particular Docker image, and spin several of the same image up, but with different configuration files. (I'd prefer to do this with environment variables, but the application that I'm Dockerizing is not partial to that.)
You have a few options. Using something like docker-compose, you could automatically build a unique image for each container using your base image as a template. For example, if you had a docker-compose.yml that look liked:
container0:
build: container0
container1:
build: container1
And then inside container0/Dockerfile you had:
FROM larsks/thttpd
COPY index.html /index.html
And inside container0/index.html you had whatever content you
wanted, then running docker-compose build would generate unique
images for each entry (and running docker-compose up would start
everything up).
I've put together an example of the above
here.
Using just the Docker command line, you can use host volume mounts,
which allow you to mount files into a container as well as
directories. Using my thttpd as an example again, you could use the
following -v argument to override /index.html in the container
with the content of your choice:
docker run -v index.html:/index.html larsks/thttpd
And you could accomplish the same thing with docker-compose via the
volume entry:
container0:
image: larsks/thttpd
volumes:
- ./container0/index.html:/index.html
container1:
image: larsks/thttpd
volumes:
- ./container1/index.html:/index.html
I would suggest that using the build mechanism makes more sense if you are trying to override many files, while using volumes is fine for one or two files.
A key difference between the two mechanisms is that when building images, each container will have a copy of the files, while using volume mounts, changes made to the file within the image will be reflected on the host filesystem.

how can I create a data-container only using docker-compose.yml?

This question is coming from an issue on the Docker's repository:
https://github.com/docker/compose/issues/942
I can't figure it out how to create a data container (no process running) with docker compose.
UPDATE: Things have changed in the last years. Please refer to the answer from #Frederik Wendt for a good and up-to-date solution.
My old answer: Exactly how to do it depends a little on what image you are using for your data-only-container. If your image has an entrypoint, you need to overwrite this in your docker-compose.yml. For example this is a solution for the official MySql image from docker hub:
DatabaseData:
image: mysql:5.6.25
entrypoint: /bin/bash
DatabaseServer:
image: mysql:5.6.25
volumes_from:
- DatabaseData
environment:
MYSQL_ROOT_PASSWORD: blabla
When you do a docker-compose up on this, you will get a container like ..._DatabaseData_1 which shows a status of Exited when you call docker ps -a. Further investigation with docker inspect will show, that it has a timestamp of 0. That means the container was never run. Like it is stated by the owner of docker compose here.
Now, as long as you don't do a docker-compose rm -v, your data only container (..._DatabaseData_1) will not loose its data. So you can do docker-compose stop and docker-compose up as often as you like.
In case you like to use a dedicated data-only image like tianon/true this works the same. Here you don't need to overwrite the entrypoint, because it doesn't exist. It seems like there are some problems with that image and docker compose. I haven't tried it, but this article could be worth reading in case you experience any problems.
In general it seems to be a good idea to use the same image for your data-only container that you are using for the container accessing it. See Data-only container madness for more details.
The other answers to this question are quite out of date, and data volumes have been supported for some time now. Example:
version: "3.9"
services:
frontend:
image: node:lts
volumes:
- myapp:/home/node/app
volumes:
myapp:
See
https://docs.docker.com/storage/volumes/#use-a-volume-with-docker-compose for details and options.
A data only container (DOC) is a container that is created only to serve as a volume provider. The container itself has no function other than that other containers can mount it's volume by using the volumes_from directive.
The DOC has to run only once to create the volume. Other containers can reference the volumes in it even if it's stopped.
The OP Question:
The docker-compose.yml starts the DOC every time you do a docker-compose up. OP asks for an option to only create container and volume, and not run it, using some sort of an create_only: true option.
As mention in the issue from the OP's question:
you either create a data container with the same name as the one specified in the docker-compose.yml, and run docker-compose up --no-recreate (the one specified in docker-compose.yml won't be recreated).
or you run a container with a simple command which never returns.
Like: tail -f /dev/null

Resources