Dockerized terraform and tfstate - docker

I have this docker container to run terraform.
alias terraform='docker run -i -t -v ~/.aws:/root/.aws:ro -v $(pwd):/app -w /app/ rubendob/terraform:0.11.8'
is just a copy of the official terraform image. Nothing fancy.
FROM golang:alpine
MAINTAINER "HashiCorp Terraform Team <terraform#hashicorp.com>"
ENV TERRAFORM_VERSION=0.11.8
RUN apk add --update git bash openssh
ENV TF_DEV=true
ENV TF_RELEASE=true
WORKDIR $GOPATH/src/github.com/hashicorp/terraform
RUN git clone https://github.com/hashicorp/terraform.git ./ && \
git checkout v${TERRAFORM_VERSION} && \
/bin/bash scripts/build.sh
RUN rm -rf /var/lib/apt/lists/*
WORKDIR $GOPATH
ENTRYPOINT ["terraform"]
So I called this way:
alias terraform='docker run -i -t -v ~/.aws:/root/.aws:ro -v $(pwd):/app -w /app/ rubendob/terraform:0.11.8'
Then I have the next folder structure and it was working ok since ups, I decided to run some terraform stuff in the dev folder.
ls -ls tf
total 0
0 drwxr-xr-x 3 ruben.ortiz staff 96 15 sep 23:43 dev
0 drwxr-xr-x 6 ruben.ortiz staff 192 11 sep 19:53 modules
0 drwxr-xr-x 4 ruben.ortiz staff 128 15 sep 12:39 prod
I ran the container like
terraform plan tf/prod/
and worked ok but container created then the .terraform folder with tfstate, and other stuff.
So if I want to run the same command but to dev environment simply cannot because it detects and previous .terraform folder
ls -lisah tf/.terraform/
total 8
901814 0 drwxr-xr-x 5 ruben.ortiz staff 160B 15 sep 12:38 .
885805 0 drwxr-xr-x 6 ruben.ortiz staff 192B 15 sep 23:54 ..
901815 0 drwxr-xr-x 15 ruben.ortiz staff 480B 16 sep 00:05 modules
901821 0 drwxr-xr-x 3 ruben.ortiz staff 96B 10 sep 23:02 plugins
901819 8 -rw-r--r-- 1 ruben.ortiz staff 567B 16 sep 18:43 terraform.tfstate
And if I enter into the dev folder, as I just set up a volume to the current directory it is not able to see the shared modules folder.
How do you do guys to workaround this?
Thanks!

I have to agree with the comments here. I would encourage you to re-evaluate the benefits you are gaining from this process.
That being said, the reason it’s causing conflicts is because you are trying to invoke 2 different workspaces from a common directory. You can avoid this by overriding the working directory when you enter the container (see https://docs.docker.com/engine/reference/run/#workdir) or simply changing directory to the correct context.
I would also suggest you try an alternative to managing environments using different workspaces.
Don’t use folders to manage your IaC environments. This leads to drift as there’s no common template for your infrastructure.
Do use a single workspace and variables to control environment specifications.
Example: Write your modules so that when you change the environment variable (var.stage is popular) the plan alters to fit your requirements. Typically the environments should vary as little as possible with quantity, exposure and capacity usually being the variable configurations. Dev might deploy 1 VM with 1 core and 1GB RAM in private topology but production may be 3 VMs with 2 cores and 4GB RAM with additional public topology. You can of course have more variation: dev may run database process on the same server as the application to save cost but production may have a dedicated DB instance. All of this can be managed by changing a single variable, ternary statements and interpolation.

Related

How to obtain consistent behavior across different hosts for docker volumes permissions?

Kindly asking for help to make sense of what I'm doing over here. I'm trying to mount as read-only a folder and have the apache user being able to read it. I'm having different behaviors on different servers
I start a container with a Dockerfile as such, note the second volume being mounted as read-only
sudo docker build -f Dockerfile -t myimage .
sudo docker run -tid --name="mycontainer" -v /my_ro_folder:/var/mystuff:ro myimage )
My Dockerfile is as follows (summarized):
FROM centos:7
ENV container docker
RUN yum -y install ....;
RUN mkdir /var/mystuff
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
Now, I see two different behaviors on two linux servers running the same distro and I don't understand why. I tried removing containers and purge the system thinking it was some cache but to no avail.
SERVER1:
ls -la /my_ro_folder
drwxrwxrwx+ 1 netadmin users 128 Jun 25 12:12 .
$ id -g netadmin ; id -u netadmin
100
1032
SERVER2:
ls -la /my_ro_folder
drwxrwxrwx+ 1 netadmin users 128 Jun 25 12:12 .
$ id -g netadmin ; id -u netadmin
100
1026
Now, on SERVER1, I get permissions just fine in the container:
drwxrwxrwx 1 1032 users 128 Jun 25 10:12 mystuff
While on SERVER2 I don't, they remain as such and consequently, the apache user can't read:
d--------- 1 1026 users 128 Jun 25 10:12 mystuff
On the containers there is no user 1026 or 1032 in neither of them. Both have the group users:x:100: though.
What is going on? why is there such a behavior .. and how can I get a consistent behavior?
Thanks
Anything that depends on bind-mounts from the host will intrinsically have host-specific behavior. On native-Linux systems, the host's user IDs will be visible inside the container, but on MacOS they'll get remapped to something else. The actual content will vary between hosts, and if you try to deploy the container to another system, you'll have to bring the content along with it.
You can avoid this by including the content in your image, and not using a bind-mount at all.
FROM centos:7
RUN yum -y install ....;
COPY mystuff /var/mystuff # creates the directory
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
# no need for a VOLUME declaration of any sort
sudo docker run -d --name="mycontainer" -p 80:80 myimage # no -v option
If you're used to having a live development environment, this isn't it. But if you're looking for a deployment setup, this means you can run the image as-is without copying other content over or worrying about filesystem permissions. If you give each image build a unique tag then you can very easily roll back to yesterday's build, and you can run a copy of the proposed container in a pre-production environment without worrying about whether you've correctly copied the files over.

Dockerfile COPY command copies file as a directory

Please note: this question mentions Java and Java keystores, but in reality has nothing to do with Java and should be answerable by anyone with sufficient knowledge of Docker and writing Dockerfiles.
I have a web service (myservice) that is a JVM application that has been Dockerized. The Dockerfile for it looks like this:
FROM openjdk:8-jdk-alpine as myenv
COPY application.yml application.yml
COPY ${KS_FILE} mykeystore.p12
COPY build/libs/myservice.jar myservice.jar
EXPOSE 9200
ENTRYPOINT [ \
"java", \
"-Dspring.config=.", \
"-Dkeystore.file=mykeystore.p12", \
"-jar", \
"myservice.jar" \
]
For the record, mykeystore.p12 is a file (not a directory!) that stores the SSL certificate that the service will serve back to any clients attempting to make a connection with it. Specifically it is an encrypted Java keystore but that is way outside the scope of this question, and is besides the point. All that matters is that you understand it is a file, not a directory. I have the file stored on my local machine.
I have the following .env file in the root of this project as well:
MYENV=local
KS_FILE=../apprunner/certs/mykeystore.p12
Hence, ../apprunner/certs/mykeystore.p12 is a relative path to a location on my file system where mykeystore.p12 lives, and I want that URI stored in the .env file and used as an environment variable from inside the Dockerfile.
I build the image like so:
docker build -t myorg/myservice .
And I run a container of that image like so:
docker run -d -p9200:9200 --name myservice --net myrunner_default --env-file .env myorg/myservice
When I SSH into the running container, I do see mykeystore.p12 on the local file system, except...
Its a directory! Not a file!
$ docker exec -it 8391601f451b /bin/sh
/ # ls -al
total 62936
drwxr-xr-x 1 root root 4096 Feb 1 21:24 .
drwxr-xr-x 1 root root 4096 Feb 1 21:24 ..
-rwxr-xr-x 1 root root 0 Feb 1 21:24 .dockerenv
-rw-r--r-- 1 root root 1510 Jan 29 16:27 application.yml
drwxr-xr-x 2 root root 4096 May 9 2019 bin
drwxr-xr-x 7 root root 4096 Jan 30 22:50 mykeystore.p12
-rw-r--r-- 1 root root 64371878 Jan 29 16:27 myservice.jar
drwxr-xr-x 5 root root 340 Feb 1 21:24 dev
drwxr-xr-x 1 root root 4096 Feb 1 21:24 etc
... etc.
And its got lots of weird, unexpected stuff in it, like source files from other directories in my project!
Clearly, something is wrong with either the use of ${KS_FILE} from inside my Dockerfile, or with how the URI value is stored in my .env file. Regardless, what do I have to change such that:
I specify the file path and name of the KS_FILE env var in my .env file; and
Between my .env and Dockerfile, that filepath + name are copied over as a file into the running container, such that when I ls -al from inside the container, I see it as a file?
There are two problems here.
You can only copy files from your build directory
You cannot copy files that exist outside of your build directory (such as ../apprunner/certs/mykeystore.p12). If you try reference this file directory in your Dockerfile, like this:
FROM openjdk:8-jdk-alpine as myenv
COPY application.yml application.yml
COPY ../apprunner/certs/mykeystore.p12 mykeystore.p12
You will see the following error:
Step 3/6 : COPY ../apprunner/certs/mykeystore.p12 mykeystore.p12
COPY failed: forbidden path outside the build context: ../apprunner/certs/mykeystore.p12 ()
Environment variable expansion doesn't work that way
From the documentation:
Environment variables (declared with the ENV statement) can also be
used in certain instructions as variables to be interpreted by the
Dockerfile. Escapes are also handled for including variable-like
syntax into a statement literally.
Since you haven't declared any ENV statements in your Dockerfile,
that environment expands as an empty string, so you are getting, in
effect:
COPY "" mykeystore.p12
This will simply copy the contents of the build directory into
mykeystore.p12.
docker build doesn't make use of a .env file.
This article might be helpful.

docker volume permission issue

I am trying to launch an app, deployed using wildfly18 in a docker container, which internally connects to my host postgresql database installation. During the container creation process, I am also mapping my container's wildfly log directory to my local i.e "host" directory via a named volume, created using the docker volume create command.
The issue is, I get a "permission denied" error when the app runs and the container tries to create log files inside the mapped volume.
My Dockerfile contents are as below:
FROM jboss/base-jdk:8
ENV WILDFLY_VERSION 18.0.1.Final
ENV WILDFLY_SHA1=ef0372589a0f08c36b15360fe7291721a7e3f7d9
ENV JBOSS_HOME /opt/jboss/wildfly
USER root
RUN cd $HOME \
&& curl -O https://download.jboss.org/wildfly/$WILDFLY_VERSION/wildfly-$WILDFLY_VERSION.tar.gz \
&& sha1sum wildfly-$WILDFLY_VERSION.tar.gz | grep $WILDFLY_SHA1 \
&& tar xf wildfly-$WILDFLY_VERSION.tar.gz \
&& mv $HOME/wildfly-$WILDFLY_VERSION $JBOSS_HOME \
&& rm wildfly-$WILDFLY_VERSION.tar.gz
COPY ./bin $JBOSS_HOME/bin
COPY ./standalone/configuration/* $JBOSS_HOME/standalone/configuration/
COPY ./modules/com $JBOSS_HOME/modules/com
COPY ./modules/system/layers/base/org/ $JBOSS_HOME/modules/system/layers/base/org/
COPY ./standalone/waffle_resource $JBOSS_HOME/standalone/waffle_resource
COPY ./standalone/waffle_resource/waffle.ear $JBOSS_HOME/standalone/deployments/
COPY ./standalone/waffle_resource/waffle-war.ear $JBOSS_HOME/standalone/deployments/
RUN chown -R jboss:jboss ${JBOSS_HOME} && chmod -R g+rw ${JBOSS_HOME}
ENV LAUNCH_JBOSS_IN_BACKGROUND true
USER jboss
EXPOSE 8989 9990
WORKDIR $JBOSS_HOME/bin
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0"]
As you can see above, I am using user JBOSS inside the container to kick off wildfly.
The commands used to create an image and run a container and also to create a volume are as below:
docker image build -t viaduct/wildfly .
docker volume create viaduct-wildfly-logs
docker run -d -v viaduct-wildfly-logs:/opt/jboss/wildfly/standalone/log --network=host \
-e "DB_DBNAME=dbname" \
-e "DB_PORT=5432" \
-e "DB_USER=xyz" \
-e "DB_PASS=" \
-e "DB_HOST=127.0.0.1" \
--name petes viaduct/wildfly
I verified the permissions within the container and my local "host" directory created by docker volume create command. Also, it's worth noting,
I am running wildlfy as user JBOSS
.
The containers permissions are as below:
[jboss#localhost /]$ ll /opt/jboss/wildfly/standalone/
total 4
drwxrwxr-x 1 jboss jboss 62 Sep 18 00:24 configuration
drwxr-xr-x 6 jboss jboss 84 Sep 18 00:23 data
drwxrwxr-x 1 jboss jboss 64 Sep 18 00:24 deployments
drwxrwxr-x 1 jboss jboss 17 Nov 15 2019 lib
*drwxr-xr-x 2 root root 6 Sep 17 23:48 log*
drwxrwxr-x 1 jboss jboss 4096 Sep 18 00:24 tmp
drwxrwxr-x 1 jboss jboss 98 Sep 18 00:23 waffle_resource
[jboss#localhost /]$ exit
and the local volume permissions are as below:
[root#localhost xyz]# cd /var/lib/docker/volumes/
[root#localhost volumes]# ll
drwxrwsr-x 3 root root 19 Sep 18 11:48 viaduct-wildfly-logs
The docker volume create command creates directory in my local machine as below:
/var/lib/docker/volumes/viaduct-wildfly-logs/_data
and the permissions for each subdirectories by default are as follows, which definitely is for maintained for security reasons:
drwx--x--x 14 root root 182 Sep 14 09:32 docker
drwx------ 7 root root 285 Sep 18 11:48 volumes
drwxrwsr-x 3 root root 19 Sep 18 11:48 viaduct-wildfly-logs
To start with, please let me know whether my strategy is correct?
Secondly, let me know the best way to fix the permission issue?
You need to create a user with the same UID/GID and give the permission on the host folder for this volume.
The server is run as the jboss user which has the uid/gid set to 1000. doc

Creating a docker container for Jupyter

I want to give a docker container to my students such that they are able to conduct experiments. I thought I use the following dockerfile:
FROM jupyter/datascience-notebook:latest
ADD ./config.json /home/jovyan/.jupyter/jupyter_notebook_config.json
ADD ./books /home/jovyan/work
So, the standard container will include a few notebooks I have created and stored in the books folder. I then build and run this container locally with
#!/usr/bin/env bash
docker build -t aaa .
docker run --rm -p "8888:8888" -v $(pwd)/books:/home/joyvan/work aaa
I build the container aaa and share again the folder books with it (although books has been copied into the image at compile time). I now open the container on port 8888. I can edit the files in the /home/joyvan/work folder but this stuff is not getting transported back to the host. Something goes terrible wrong. Is it because I add the files during the docker build and then share them again in the -v ...?
I have played with various options. I have added the local user to the users group. I do chown on all files in books. All my files show up as root:root in the container. I am then joyvan in the container and do not have write access to those files. How would I make sure the files are owned by joyvan?
EDIT:
Some other elements :
tom#thomas-ThinkPad-T450s:~/babynames$ docker exec -it cranky_poincare /bin/bash
jovyan#5607ac2bcaae:~$ id
jovyan uid=1000(jovyan) gid=100(users) groups=100(users)
jovyan#5607ac2bcaae:~$ cd work/
jovyan#5607ac2bcaae:~/work$ ls
test.txt text2.txt
jovyan#5607ac2bcaae:~/work$ ls -ltr
total 4
-rw-rw-r-- 1 root root 5 Dec 12 19:05 test.txt
-rw-rw-r-- 1 root root 0 Dec 12 19:22 text2.txt
on the host:
tom#thomas-ThinkPad-T450s:~/babynames/books$ ls -ltr
total 4
-rw-rw-r-- 1 tom users 5 Dez 12 20:05 test.txt
-rw-rw-r-- 1 tom users 0 Dez 12 20:22 text2.txt
tom#thomas-ThinkPad-T450s:~/babynames/books$ id tom
uid=1001(tom) gid=1001(tom) groups=1001(tom),27(sudo),100(users),129(docker)
You can try:
FROM jupyter/datascience-notebook:latest
ADD ./config.json /home/jovyan/.jupyter/jupyter_notebook_config.json
ADD ./books /home/jovyan/work
RUN chown joyvan /books
if that user already exists, but with RUN you can execute all commands in your docker file.

Unable to modify files in container from docker

I am attempting to build an imaging by modifying some of the files in an existing image. However, the files are not changed by RUN commands. My dockerfile is
FROM vromero/activemq-artemis
ADD . .
RUN ls
RUN whoami
# Overwrite existing password file. The existing file is invulnerable, and
# cannot be modified by docker. I have no idea why.
RUN rm -f /var/lib/artemis/etc/artemis-users.properties
RUN ls -l /var/lib/artemis/etc
RUN mv passwords.txt /var/lib/artemis/etc/artemis-users.properties
RUN cat /var/lib/artemis/etc/artemis-users.properties
RUN touch /var/lib/artemis/etc/touch-test
# Add the predefined queues
RUN sed -i.bak '/<core/r queues.xml' /var/lib/artemis/etc/broker.xml
# EOF
The base image is from the public docker repository. When I run it, I get the following output
$ docker build .
Sending build context to Docker daemon 4.608 kB
Step 0 : FROM vromero/activemq-artemis
---> 4e0f54c798cc
Step 1 : ADD . .
---> 3efde5a1fdea
Removing intermediate container c8621adc900b
Step 2 : RUN ls
---> Running in 5c5dca9449da
Dockerfile
artemis
artemis-service
passwords.txt
queues.xml
---> 22c541f98339
Removing intermediate container 5c5dca9449da
Step 3 : RUN whoami
---> Running in f11fcd2e2c5b
root
---> 15ee9aeb4c15
Removing intermediate container f11fcd2e2c5b
Step 4 : RUN rm -f /var/lib/artemis/etc/artemis-users.properties
---> Running in ab4383f0bb91
---> 10877bdb08ee
Removing intermediate container ab4383f0bb91
Step 5 : RUN ls -l /var/lib/artemis/etc
---> Running in a5669c8808e8
total 24
-rw-r--r-- 1 artemis artemis 959 Oct 4 05:40 artemis-roles.properties
-rw-r--r-- 1 artemis artemis 968 Oct 4 05:40 artemis-users.properties
-rwxrwxr-x 1 artemis artemis 1342 Oct 4 05:40 artemis.profile
-rw-r--r-- 1 artemis artemis 1302 Oct 4 05:40 bootstrap.xml
-rw-r--r-- 1 artemis artemis 4000 Oct 4 05:40 broker.xml
-rw-r--r-- 1 artemis artemis 2203 Oct 4 05:40 logging.properties
---> 02e3acc58653
Removing intermediate container a5669c8808e8
Step 6 : RUN mv passwords.txt /var/lib/artemis/etc/artemis-users.properties
---> Running in 68000aa34f6b
---> ec057d5adc67
Removing intermediate container 68000aa34f6b
Step 7 : RUN cat /var/lib/artemis/etc/artemis-users.properties
---> Running in 934a36d8c4d1
## ---------------------------------------------------------------------------
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements. See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License. You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
## ---------------------------------------------------------------------------
apollo=ollopaehcapa ---> ca1bad8a8903
Removing intermediate container 934a36d8c4d1
Step 8 : RUN touch /var/lib/artemis/etc/touch-test
---> Running in cb931c5cfcd1
---> 6961b4fcde75
Removing intermediate container cb931c5cfcd1
Step 9 : RUN sed -i.bak '/<core/r queues.xml' /var/lib/artemis/etc/broker.xml
---> Running in a829642b29ab
---> effd394fc02f
Removing intermediate container a829642b29ab
Successfully built effd394fc02f
The ADD . . has worked, as passwords.txt and queues.xml both show up in the ls. whoami shows that the current user is root, so there should be no permissions problems.
However, the existing files are not changed. If I run the image but use bash as the start command (see below), none of the files have a current date, although the file that was mv'ed to replace an existing file is gone. If I paste the sed command into the shell, it does update the file.
$ docker run -it effd394fc02f bash
root#51d1cc0a94cb:/var/lib/artemis/bin# ls -l
total 16
-rw-r--r-- 1 root root 543 Oct 21 22:12 Dockerfile
-rwxrwxr-x 1 artemis artemis 3416 Oct 4 05:40 artemis
-rwxrwxr-x 1 artemis artemis 3103 Oct 4 05:40 artemis-service
-rw-r--r-- 1 root root 329 Oct 21 22:18 queues.xml
root#51d1cc0a94cb:/var/lib/artemis/bin# cd ../etc
root#51d1cc0a94cb:/var/lib/artemis/etc# ls -l
total 24
-rw-r--r-- 1 artemis artemis 959 Oct 4 05:40 artemis-roles.properties
-rw-r--r-- 1 artemis artemis 968 Oct 4 05:40 artemis-users.properties
-rwxrwxr-x 1 artemis artemis 1342 Oct 4 05:40 artemis.profile
-rw-r--r-- 1 artemis artemis 1302 Oct 4 05:40 bootstrap.xml
-rw-r--r-- 1 artemis artemis 4000 Oct 4 05:40 broker.xml
-rw-r--r-- 1 artemis artemis 2203 Oct 4 05:40 logging.properties
Why are these files not being changed by the run commands?
The actual problem was related to how the base image was built. If you run docker history --no-trunc vromero/activemq-artemis, you see these commands (among others):
<id> 6 weeks ago /bin/sh -c #(nop) VOLUME [/var/lib/artemis/etc] 0 B
<id> 6 weeks ago /bin/sh -c #(nop) VOLUME [/var/lib/artemis/tmp] 0 B
<id> 6 weeks ago /bin/sh -c #(nop) VOLUME [/var/lib/artemis/data] 0 B
The Dockerfile volume documentation states
Note: If any build steps change the data within the volume after it
has been declared, those changes will be discarded.
This means that the configuration in the base image is locked.
I solved my problem by creating my own dockerfile based on the output of the history command, without the volume lines.
Not a complete answer, but at least a clue: you don't change the entrypoint of the built image.
That means your image will still execute the one from vromero/activemq-artemis, which, according to its Dockerfile is:
ENTRYPOINT ["/docker-entrypoint.sh"]
And docker-entrypoint.sh might reset some of your changes on docker run.
There are two RUN commands in Dockerfile.
You are running this: RUN <command> (the command is run in a shell - /bin/sh -c (shell form)
The other one is this: RUN ["executable", "param1", "param2"] (exec form)
Try this:
RUN ["rm", "-f", "/var/lib/artemis/etc/artemis-users.properties"]
RUN ["ls", "-l", "/var/lib/artemis/etc"]
RUN ["mv", "passwords.txt", "/var/lib/artemis/etc/artemis-users.properties"]
RUN ["cat", "/var/lib/artemis/etc/artemis-users.properties"]
RUN ["touch", "/var/lib/artemis/etc/touch-test"]
# Add the predefined queues
RUN ["sed", "-i.bak", "'/<core/r queues.xml'", "/var/lib/artemis/etc/broker.xml"]

Resources