Running apache and cron in docker - apache

I understood there should be only one process running on foreground in a docker container. Is there any chance of running both apache and cron together in foreground? A quick search says there is something called supervisord to achieve this. But is there any other method using Entrypoint script or CMD?
Here is my Dockerfile
FROM alpine:edge
RUN apk update && apk upgrade
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk /repositories
RUN apk add \
bash \
apache2 \
php7-apache2 \
php7 \
curl \
php7-mysqli \
php7-pdo \
php7-pdo_mysql
RUN cp /usr/bin/php7 /usr/bin/php
RUN mkdir /startup
COPY script.sh /startup
RUN chmod 755 /startup/script.sh
ENTRYPOINT ["/startup/script.sh"]
The content of script.sh is pasted below
#!/bin/bash
# start cron
/usr/sbin/crond -f -l 8
# start apache
httpd -D FOREGROUND
When the docker is run with this image only crond is running and most interestingly when I kill the cron then apache starts and running in the foreground.
I am using aws ecs ec2 to run the docker container using task definition and a service.

Docker container is running while main process inside it is running. So if you want to run two services inside docker container, one of them has to be run in a background mode.
I suggest to get rid of scrip.sh at all and replace it just with one CMD layer:
CMD ( crond -f -l 8 & ) && httpd -D FOREGROUND
The final Dockerfile is:
FROM alpine:edge
RUN apk update && apk upgrade
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk add \
bash \
apache2 \
php7-apache2 \
php7 \
curl \
php7-mysqli \
php7-pdo \
php7-pdo_mysql
RUN cp /usr/bin/php7 /usr/bin/php
CMD ( crond -f -l 8 & ) && httpd -D FOREGROUND

The problem is that you're running crond -f, without telling bash to run it in the background, basically keeping bash waiting for crond to exit to continue running the script. There's two solutions for this:
Remove the -f flag (that flag causes crond to run in the foreground).
Add & at the end of the crond line, after -l 8 (I wouldn't recommend this).
Also, I'd start apache with exec:
exec httpd -D FOREGROUND
Otherwise /startup/script.sh will remain running, while it's not doing anything useful anymore anyway. exec tells bash to replace the current process with the command to execute.

Related

podman - How to Start a Process in a Containerfile?

I have put a script with an endless loop inside a Containerfile.
When I go inside the container and run that script in the background I can see that the process is running by doing a ps -ef.
But when I try to start the process inside the Containerfile it is not running, even though the podman build and podman run commands are without error.
I am using rootless podman.
This is my Containerfile:
$ cat Containerfile
FROM alpine
RUN apk update
RUN apk add vim
RUN apk add bash
COPY ./useless_process.sh /home
RUN bash /home/useless_process.sh &
# how to build:
# podman build . -t "manualpihimage"
# how to run:
# podman run -it --name "manualpihcontainer" manualpihimage
I have also tried using the CMD and the ENTRYPOINT commands but the process did not start.
The expectation was that the process would run in the background.
I have tried it with Containerfile as follows. Note that I removed the useless & - makes no sense in the context of the container and used CMD because we don't want to run it while building the image but when we start the container.
FROM alpine
RUN apk update
RUN apk add vim
RUN apk add bash
COPY ./useless_process.sh /home
CMD bash /home/useless_process.sh
I created useless_process.sh with:
#!/bin/sh
while `/bin/true`; do
date
sleep 1
done
Then podman build . -t=image1 and podman run -d --name=container1 image1 to start it detached.
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0744f29bec7c localhost/image1:latest /bin/sh -c bash /... 22 seconds ago Up 23 seconds ago container1
And we can see our useless process is running
$ podman exec -it container1 /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 bash /home/useless_process.sh
188 root 0:00 /bin/sh
197 root 0:00 sleep 1
198 root 0:00 ps

RuntimeWarning:You're running the worker with superuser privileges:this is absolutely not recommended

I am using django+celery+redis,celery==4.4.0 in local it is working fine but when I am dockerizing it , I am getting the above error.
I am using following commands to run in local as well as inside container
**CMDs**
celery -A nrn worker -l info
docker run -d -p 6379:6379 redis
flower -A nrn --port=5555
Any help is highly appreciated
*settings.py**
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_BROKER_URL = os.environ.get('redis', 'redis://127.0.0.1:6379/')
Take a look in the documentation. It's a warning, though, not an error (see the code). Running Celery under root is an error only when you allow pickle serialization which is not enabled by default (see here).
However, it's still the best practice to run Celery with lower privileges. In Docker (with Debian based image), I choose to run Celery under nobody:nogroup. I use this Dockerfile:
FROM python:3.6
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
WORKDIR /srv/celery
COPY ./app app
COPY ./requirements.txt /tmp/requirements.txt
COPY ./celery.sh celery.sh
RUN pip install --no-cache-dir \
-r /tmp/requirements.txt
VOLUME ["/var/log/celery", "/var/run/celery"]
CMD ["./celery.sh"]
where celery.sh looks as follows:
#!/usr/bin/env bash
mkdir -p /var/run/celery /var/log/celery
chown -R nobody:nogroup /var/run/celery /var/log/celery
exec celery --app=app worker \
--loglevel=INFO --logfile=/var/log/celery/worker-example.log \
--statedb=/var/run/celery/worker-example#%h.state \
--hostname=worker-example#%h \
--queues=celery.example -O fair \
--uid=nobody --gid=nogroup

Apache Tomcat 8 not starting within a docker container

I am experimenting with Docker and am very new to it. I am struck at a point for a long time and am not getting a way through and hence came up with this question here...
Problem Statement:
I am trying to create an image from a docker file containing Apache and lynx installation. Once done I am trying to access tomcat on 8080 of the container which is in turn forwarded to the 8082 of the host. But when running the image I never get tomcat started in the container.
The Docker file
FROM ubuntu:16.10
#Install Lynx
Run apt-get update
Run apt-get install -y lynx
#Install Curl
Run apt-get install -y curl
#Install tools: jdk
Run apt-get update
Run apt-get install -y openjdk-8-jdk wget
#Install apache tomcat
Run groupadd tomcat
Run useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat
Run cd /tmp
Run curl -O http://apache.mirrors.ionfish.org/tomcat/tomcat- 8/v8.5.12/bin/apache-tomcat-8.5.12.tar.gz
Run mkdir /opt/tomcat
Run tar xzvf apache-tomcat-8*tar.gz -C /opt/tomcat --strip-components=1
Run cd /opt/tomcat
Run chgrp -R tomcat /opt/tomcat
Run chmod -R g+r /opt/tomcat/conf
Run chmod g+x /opt/tomcat/conf
Run chown -R tomcat /opt/tomcat/webapps /opt/tomcat/work /opt/tomcat/temp opt/tomcat/logs
Run cd /opt/tomcat/bin
Expose 8080
CMD /opt/tomcat/bin/catalina.sh run && tail -f /opt/tomcat/logs/catalina.out
When the image is built I tried running the container by the two below methods
docker run -d -p 8082:8080 imageid tail -f /dev/null
While using the above, container is running but tomcat is not started inside the container and hence not accessible from localhost:8082. Also I do not see anything if I perform docker logs longcontainerid
docker run -d -p 8082:8080 imageid /path/to/catalina.sh start tail -f /dev/null
I see tomcat started when I do docker logs longconatainrid
While using the above the container is started and stopped immediately and is not running as I can see from docker ps and hence again not accessible from localhost:8082.
Can anyone please tell me where I am going wrong?
P.s. I searched a lot on the internet but could not get the thing right. Might be there is some concept that i am not getting clearly.
Looking at the docker run command documentation, the doc states that any command passed to the run will override the original CMD in your Dockerfile:
As the operator (the person running a container from the image), you can override that CMD instruction just by specifying a new COMMAND
1/ Then when you run:
docker run -d -p 8082:8080 imageid tail -f /dev/null
The container is run with COMMAND tail -f /dev/null, the original command starting tomcat is overridden.
To resolve your problem, try to run:
docker run -d -p 8082:8080 imageid
and
docker log -f containerId
To see if tomcat is correctly started.
2/ You should not use the start argument with catalina.sh. Have a look at this official tomcat Dokerfile, the team uses :
CMD ["catalina.sh", "run"]
to start tomcat (when you use start, docker ends container at the end of the shell script and tomcat will start but not maintain a running process).
3/ Finally, why don't you use tomcat official image to build your container? You could just use the :
FROM tomcat:latest
directive at the beginning of your Dockerfile, and add you required elements (new files, webapps war, settings) to the docker image.

How do I start plack application on boot

Does anyone know how to start a plack application on boot.
The os is raspbian(raspberry pi).
I think i have run it as a normal user(pi). That's how i start it manually.
I have tried adding something like this to rc.local but without success
su pi -c 'cd /path/to/app && plackup -d -p 5000 -r -R ./lib,./t -a ./bin/app.psgi &'
This will in-turn be used by Apache and the app is written in dancer2 if it makes any difference.
On a raspberry pi I use systemd to create and start a service, in the file:
/etc/systemd/system/dancer.service
[Unit]
Description=NCI Starman Dancer App
After=syslog.target
[Service]
Type=forking
ExecStart=/usr/local/bin/starman --daemonize -l 127.0.0.1:3004 \
--user myuser --group myuser --workers 8 -D -E production \
--pid /var/run/dancer.pid -I/home/myuser/webservers/Dancer/lib \
--error-log=/home/myuser/logs/dancer_error.log \
/home/myuser/webservers/Dancer/bin/app.psgi
Restart=always
[Install]
WantedBy=multi-user.target
And then I enable this with systemctl enable dancer.service
Or start it manually with systemtctl start dancer.service
Instead of startman, you can of course use plackup.
The issue was that the perl 5 environment variables were not initialised (which are in .bashrc).
so the solution was to run the plackup command inside bash -i so that it reads .bashrc or set the PERL5LIB before invoking plackup
You may also want to use monit or supervisord to be sure your app is always run and will be restarted in case of kill by any reason, for example OOM

Starting a service inside of a Dockerfile

I'm building a Docker container and in this container I am downloading the Apache service. Is it possible to automatically start the Apache service at some point? Systemctl start httpd does not work inside of the Dockerfile.
Basically, I want the apache service to be started when the docker container is started.
FROM centos:7
MAINTAINER me <me#me.com>
RUN yum update -y && yum install -y httpd php
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
EXPOSE 80
EXPOSE 443
CMD ["/usr/sbin/init"]
Try using CMD ["/usr/sbin/httpd", "-DFOREGROUND"].
You also can run :
docker run -d <image name> /usr/sbin/httpd -DFOREGROUND
According to the Docker reference (Entrypoint reference), in the scenario you describe, you would use ENTRYPOINT, as you want your web server to "immutably" start. CMD is for commands or command line options that you are likely change/be overwritten:
Command line arguments to docker run will be appended after all elements in an exec form ENTRYPOINT, and will override all elements specified using CMD. This allows arguments to be passed to the entry point, i.e., docker run -d will pass the -d argument to the entry point.
If you must override an ENTRYPOINT, e.g. for testing/diagnostics, use the specific --entrypoint option.
Further:
You can use the exec form of ENTRYPOINT to set fairly stable default commands and arguments and then use either form of CMD to set additional defaults that are more likely to be changed.
So, ENTRYPOINT for the fixed services/application part, CMD for overrideable commands or options.
Using both ENTRYPOINT and CMD allows you to set a "fixed" commands part (including options) and a "variable" part. Like so:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
Which means, in your case you may consider to have:
ENTRYPOINT ["/usr/sbin/httpd"]
CMD ["-DFOREGROUND"]
Which allows you do:
docker run -d <image name>
when you want to run your web server in the foreground, but
docker run -d <image name> -DBACKGROUND
if you want that same server to run with the -DBACKGROUND option overriding only the -DFOREGROUND part.