docker-compose COPY before running endrypoint - docker

Using docker desktop with WSL2, the ultimate aim is to run a shell command to generate local SSL certs before starting an nginx service.
to docker up we have
version: '3.6'
services:
# Frontend
rp:
environment:
- COMPOSE_CONVERT_WINDOWS_PATHS=1
container_name: revproxy
image: nginx:latest
user: root
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- .\conf:/home/conf
- .\scripts:/home/scripts
so far so good, now we would like to add a pre startup script to create the ssl certs before launching the nginx server /home/scripts/certs.sh
mkdir -p /home/ssl/certs
mkdir -p /home/ssl/private
openssl req -x509 -nodes -days 365 -subj "/C=CA/ST=QC/O=Company, Inc./CN=zero.url" -addext "subjectAltName=DNS:mydomain.com" -newkey rsa:2048 -keyout /home/ssl/private/nginx-zero.key -out /home/ssl/certs/nginx-zero.crt;
Now adding the following to docker-compose.yml causes the container to bounce between running to rebooting and keeps recreating the certs via the script the exits the container. no general error message. I assume the exit code means the container is exiting correctly, that then triggers the restart.
command: /bin/sh -c "/home/scripts/certs.sh"
following other answers, adding exec "$#" makes no difference.
as an alternative I tried to copy the script into the pre nginx launch folder docker-entrypoint.d. this creates an error on docker up
version: '3.6'
services:
# Frontend
rp:
environment:
- COMPOSE_CONVERT_WINDOWS_PATHS=1
container_name: revproxy
image: nginx:latest
user: root
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- .\conf:/home/conf
- .\scripts:/home/scripts
COPY /home/scripts/certs.sh /docker-entrypoint.d/certs.sh
this generates an error
ERROR: yaml.scanner.ScannerError: while scanning a simple key
in ".\docker-compose.yml", line 18, column 7
could not find expected ':'
in ".\docker-compose.yml", line 18, column 64
The terminal process "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command docker-compose -f "docker-compose.yml" up -d --build" terminated with exit code: 1.
So what are the options for running a script before starting the primary docker-entrypoint.sh script
UPDATE:
as per suggestion in comment, changing the format of the flag did not help,
version: '3.6'
services:
# Frontend
rp:
environment:
- COMPOSE_CONVERT_WINDOWS_PATHS: 1
container_name: revproxy
image: nginx:latest
user: root
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- .\conf:/home/conf
- .\dc_scripts:/home/scripts
COPY /home/scripts/certs.sh /docker-entrypoint.d/certs.sh
ERROR: yaml.scanner.ScannerError: while scanning a simple key
in ".\docker-compose.yml", line 17, column 7
could not find expected ':'
in ".\docker-compose.yml", line 18, column 7
The terminal process "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command docker-compose -f "docker-compose.yml" up -d --build" terminated with exit code: 1.

Dockerfiles are used to buid images, and contains a list of commands like RUN, EXEC and COPY. They have a very shell script like syntax with one command per line (for the most part).
A docker compose file on the other hand is a yaml formatted file that is used to deploy built images to docker as running services. You cannot put commands like COPY in this file.
You can, for local deployments, on non windows systems, map individual files in in the volumes section:
volumes:
- .\conf:/home/conf
- .\scripts:/home/scripts
- ./scripts/certs.sh:/usr/local/bin/certs.sh
But this syntax only works on linux and MacOS hosts - I believe.
An alternative is to restructure your project with a Dockerfile and a docker-compose.yml file.
With a Dockerfile
FROM nginx:latest
COPY --chmod=0755 scripts/certs.sh /usr/local/bin
ENTRYPOINT ["certs.sh"]
Into the docker-compose, add a build: node with the path to the Dockerfile. "." will do. docker-compose build will be needed to force a rebuild if the Dockerfile changes after the first time.
version: '3.9'
services:
revproxy:
environment:
COMPOSE_CONVERT_WINDOWS_PATHS: 1
image: nginx:custom
build: .
user: root
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- .\conf:/home/conf
- .\scripts:/home/scripts
Now, that youve changed the entrypoint of the nginx container to your custom script, you need to chain to the original one, and call it with the original command.
So, certs.sh needs to look like:
#!/bin/sh
# your cert setup here
# this should remove "certs.sh" from the beginning of the current parameter list.
shift 1
# and now, transfer control to the original entrypoint, with the commandline that was passed.
exec "./docker-entrypoint.sh" "$#"
docker inspect nginx:latest was used to discover the original entrypoint.
Added after edit:
Also, COMPOSE_CONVERT_WINDOWS_PATHS doesn't look like an environment variable that nginx is going to care about. This variable should probably be set on your windows user environment so it is available before running docker-compose.
C:\> set COMPOSE_CONVERT_WINDOWS_PATHS=1
C:\> docker-compose build
...
C:\> docker-compose up
...
Also, nginx on docker hub indicates that /etc/nginx is the proper configuration folder for nginx, so I don't think that mapping things to /home/... is going to do anything. nginx should display a default page however.

Related

JasperReports as Tomcat default application in URL

Standard deployment of jasperreports (docker pull bitnami/jasperreports - under Ubuntu 20.04.3 LTS)
version: '3.7'
services:
jasperServerDB:
container_name: jasperServerDB
image: docker.io/bitnami/mariadb:latest
ports:
- '3306:3306'
volumes:
- './jasperServerDB_data:/bitnami/mariadb'
environment:
- MARIADB_ROOT_USER=mariaDbUser
- MARIADB_ROOT_PASSWORD=mariaDbPassword
- MARIADB_DATABASE=jasperServerDB
jasperServer:
container_name: jasperServer
image: docker.io/bitnami/jasperreports:latest
ports:
- '8085:8080'
volumes:
- './jasperServer_data:/bitnami/jasperreports'
depends_on:
- jasperServerDB
environment:
- JASPERREPORTS_DATABASE_HOST=jasperServerDB
- JASPERREPORTS_DATABASE_PORT_NUMBER=3306
- JASPERREPORTS_DATABASE_USER=dbUser
- JASPERREPORTS_DATABASE_PASSWORD=dbPassword
- JASPERREPORTS_DATABASE_NAME=jasperServerDB
- JASPERREPORTS_USERNAME=adminUser
- JASPERREPORTS_PASSWORD=adminPassword
restart: on-failure
The reporting server is behind nginx reverse proxy which points to port 8085 of the docker machine.
Everything works as expected on https://my.domain.com/jasperserver/ url.
It is required to have JasperReports server responding on only https://my.domain.com/ url.
What is the recommended/best approach to configure the container (default Tomcat application) which can survive container's restarts and updates?
Some results from searching the net:
https://cwiki.apache.org/confluence/display/tomcat/HowTo#HowTo-HowdoImakemywebapplicationbetheTomcatdefaultapplication?
https://coderanch.com/t/85615/application-servers/set-application-default-application
https://benhutchison.wordpress.com/2008/07/30/how-to-configure-tomcat-root-context/
Which doubtfully are applicable to bitnami containers.
Hopefully there is a simple image configuration which could be included in the docker-compose.yml file.
Reference to GitHub Bitnami JasperReports Issues List where the same question is posted.
After trying all recommended ways to achieve the requirement, seems that Addendum 1 from cwiki.apache.org is the best one.
Submitted a PR to bitnami with single parameter fix of the use case: ROOT URL setting
Here is a workaround in case the above PR doesn't get accepted
Step 1
Create a .sh (e.g start.sh) file in the docker-compose.yml folder with following content:
#!/bin/bash
docker-compose up -d
echo "Building JasperReports Server..."
#Long waiting period to ensure the container is up and running (health checks didn't worked out well)
sleep 180;
echo "...completed!"
docker exec -u 0 -it jasperServer sh -c "rm -rf /opt/bitnami/tomcat/webapps/ROOT && rm /opt/bitnami/tomcat/webapps/jasperserver && ln -s /opt/bitnami/jasperreports /opt/bitnami/tomcat/webapps/ROOT"
echo "Ready to rock!"
Note that the container name must match the one from your docker-compose.yml file.
Step 2
Start the container by typing: $sh ./start.sh instead of $docker-compose up -d.
Step 3
Give it some time and try https://my.domain.com/.

Unable to access site in docker-compose

I've been using: docker build -t devstack .
docker run --rm -p 443:443 -it -v ~/code:/code devstack
That has been working fine for me so far. I've been able to access the site as expected through my browser. I set my hosts file to point devstack.com to 127.0.0.1 and the site loads nicely. Now I'm trying to use docker-compose so I can use some of the functionality there to more easily connect with AWS.
services:
web:
build:
context: .
network_mode: "bridge"
ports:
- "443"
- "80"
volumes:
- ~/code:/code
image: devstack:latest
So I run docker-compose build which gives me the familiar build stuff from Dockerfile.
Then I run docker-compose run web which puts me into the VM where I start apache (doing it manually at the moment), hit top to verify it’s running, then tail the log files. But when I attempt to hit the site in my browser, I get: devstack.com refused to connect. and no logs in the apache log files, so it's not even getting to apache. So something about the ports isn't opening up to me. Any idea what I need to change to make this work?
Edit: Updated file. Still same problem:
version: "3"
services:
web:
build:
context: .
# Same issue with both of these:
# network_mode: "bridge"
# network_mode: "host"
ports:
- "443:443"
- "80:80"
volumes:
- ~/code:/code
tty: true
This is what I did to get it working. I used the example project docker-compose showed in their documentation, which runs a test app on port 5000. That worked, so I knew it could be done.
I updated my docker-compose.yml to be very similar to the one in the test project. So it looks like this now:
version: "3"
services:
web:
build: .
ports:
- "443:443"
- "80:80"
volumes:
- ~/code:/code
Then I created an entry.sh file which will start apache, and added this to my Dockerfile:
# copy the entry file which will start apache
COPY entry.sh entry.sh
RUN chmod +x entry.sh
# start apache
CMD ./entry.sh; tail -f /var/log/apache2/*.log
So now when I do docker-compose up, it will start apache and tail the apache log files. So I immediately see apache log files output to terminal. Then I'm able to access the site. Basically the problem was just with the VM exiting. This was the only way I could find to keep it from exiting without doing tty=true in the docker-compose, which while it kept it from exiting, wouldn't publish the ports.

How to run Symfony console command inside the docker container

I am trying to run Symfony 3 console command inside of my docker container but not able to getting proper output.
docker-compose.yaml
version: '3.4'
services:
app:
build:
context: .
target: symfony_docker_php
args:
SYMFONY_VERSION: ${SYMFONY_VERSION:-}
STABILITY: ${STABILITY:-stable}
volumes:
# Comment out the next line in production
- ./:/srv/app:rw,cached
# If you develop on Linux, comment out the following volumes to just use bind-mounted project directory from host
- /srv/app/var/
- /srv/app/var/cache/
- /srv/app/var/logs/
- /srv/app/var/sessions/
environment:
- SYMFONY_VERSION
nginx:
build:
context: .
target: symfony_docker_nginx
depends_on:
- app
volumes:
# Comment out the next line in production
- ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
- ./public:/srv/app/public:ro
ports:
- '80:80'
My console command
docker-compose exec nginx php bin/console
It returns the following response
the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'
Copy from https://docs.docker.com/compose/reference/exec/
To disable this behavior, you can either the -T flag to disable pseudo-tty allocation.
docker-compose exec -T nginx <command>
Or, set COMPOSE_INTERACTIVE_NO_CLI value as 1
export COMPOSE_INTERACTIVE_NO_CLI=1
For php bin/console to run you need to run from app container like below.
docker-compose exec -T app php bin/console

Dockercompose can't access using hostname

I am quite new to docker but am trying to use docker compose to run automation tests against my application.
I have managed to get docker compose to run my application and run my automation tests, however, at the moment my application is running on localhost when I need it to run against a specific domain example.com.
From research into docker it seems you should be able to hit the application on the hostname by setting it within links, but I still don't seem to be able to.
Below is the code for my docker compose files...
docker-compose.yml
abc:
build: ./
command: run container-dev
ports:
- "443:443"
expose:
- "443"
docker-compose.automation.yml
tests:
build: test/integration/
dockerfile: DockerfileUIAuto
command: sh -c "Xvfb :1 -screen 0 1024x768x16 &>xvfb.log && sleep 20 && DISPLAY=:1.0 && ENVIRONMENT=qa BASE_URL=https://example.com npm run automation"
links:
- abc:example.com
volumes:
- /tmp:/tmp/
and am using the following command to run...
docker-compose -p tests -f docker-compose.yml -f docker-compose.automation.yml up --build
Is there something I'm missing to map example.com to localhost?
If the two containers are on the same Docker internal network, Docker will provide a DNS service where one can talk to the other by just its container name. As you show this with two separate docker-compose.yml files it's a little tricky, because Docker Compose wants to isolate each file into its own separate mini-Docker world.
The first step is to explicitly declare a network in the "first" docker-compose.yml file. By default Docker Compose will automatically create a network for you, but you need to control its name so that you can refer to it from elsewhere. This means you need a top-level networks: block, and also to attach the container to the network.
version: '3'
networks:
abc:
name: abc
services:
abc:
build: ./
command: run container-dev
ports:
- "443:443"
networks:
abc:
aliases:
- example.com
Then in your test file, you can import that as an external network.
version: 3
networks:
abc:
external: true
name: abc
services:
tests:
build: test/integration/
dockerfile: DockerfileUIAuto
command: sh -c "Xvfb :1 -screen 0 1024x768x16 &>xvfb.log && sleep 20 && npm run automation"
environment:
DISPLAY: "1.0"
ENVIRONMENT: qa
BASE_URL: "https://example.com"
networks:
- abc
Given the complexity of what you're showing for the "test" container, I would strongly consider running it not in Docker, or else writing a shell script that launches the X server, checks that it actually started, and then runs the test. The docker-compose.yml file isn't the only tool you have here.

Go applications fails and exits when running using docker-compose, but works fine with docker run command

I am running all of these operations on a remove server that is a
VM running Ubuntu 16.04.5 x64.
My Go project's Dockerfile looks like:
FROM golang:latest
ADD . $GOPATH/src/example.com/myapp
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
#CMD ["./myapp"]
When I run the docker container using docker-compose up -d, the Go application exits and I see this in the docker logs:
myapp_1 | /bin/sh: 1: ./myapp: Exec format error docker_myapp_1
exited with code 2
If I locate the image using docker images and run the image like:
docker run -it 75d4a95ef5ec
I can see that my golang applications runs just fine:
viper environment is: development HTTP server listening on address:
":3005"
When I googled for this error some people suggested compiling with some special flags but I am running this container on the same Ubuntu host so I am really confused why this isn't working using docker.
My docker-compose.yml looks like:
version: "3"
services:
openresty:
build: ./openresty
ports:
- "80:80"
- "443:443"
depends_on:
- myapp
env_file:
- '.env'
restart: always
myapp:
build: ../myapp
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
ports:
- "3005:3005"
depends_on:
- db
- redis
- memcached
env_file:
- '.env'
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- "/home/deploy/v/redis:/data"
restart: always
memcached:
image: memcached
ports:
- "11211:11211"
restart: always
db:
image: postgres:9.4
volumes:
- "/home/deploy/v/pgdata:/var/lib/postgresql/data"
restart: always
Your docker-compose.yml file says:
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
which means your host system's source directory is mounted over, and hides, everything that the Dockerfile builds. ./myapp is the host's copy of the myapp executable and if something is different (maybe you have a MacOS or Windows host) that will cause this error.
This is a popular setup for interpreted languages where developers want to run their application without running a normal test-build-deploy sequence, but it doesn't really make sense for a compiled language like Go where you don't have a choice. I'd delete this block entirely.
The Go container stops running because of this:
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
You are switching directories to $GOPATH/src/example.com/myapp where you build your app, however, your entry point is pointing to the wrong location.
To solve this, you either copy the app into the root directory and keep the same ENTRYPOINT command or you copy the application to a different location and pass the full path such as:
ENTRYPOINT /my/go/app/location

Resources