Within a Docker image, "Slapd stop" succeeds but slapd is still running - ldap

I'm trying to create an openLDAP docker image with custom schema, and I would like to have a working LDAP service before modifying it.
I installed slapd and ldap-utils in my docker image, by putting in the dockerfile:
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y slapd ldap-utils
At this point, when I open a bash in a new container, service slapd status or /etc/init.d/slapd status output both "slapd is not running". Indeed, the policy-rc denies the execution of start after the installation of a package.
Well, no problem, service slapd start returns OK and starts the slapd service. I can search in my LDAP, modify it, everything is fine.
The problem comes when I want to restart the slapd service. service slapd restart, or service slapd force-reload or service slapd stop and service slapd start all fail at the "start" comand. The "stop" command returns OK. However, this time, service slapd status returns "slapd is running". Also, I still can search in my LDAP.
To know a bit more about what happened, I tried to start the slapd service with the debug option, as:
slapd -h 'ldap:/// ldapi:///' -g openldap -u openldap -F /etc/ldap/slapd.d -d stats
Unfortunately, this hangs at "slapd starting" and never finishes.
Thanks for any help :)

I have the same issue. When being inside the container the only way I find to stop slapd is pkill slapd
Nevertheless this is not working with Dockerfile and run pkill slapd

I just encountered the same issue in a docker image based on minideb (Debian Buster).
When executing service slapd stop, the stop_slapd shell function of the /etc/init.d/slapd script is invoked, which in turn executes this command:
start-stop-daemon --stop --quiet --oknodo --retry TERM/10 \
--pidfile "/var/run/slapd/slapd.pid" \
--exec /usr/sbin/slapd 2>&1
When you execute this command in a root shell and omit the --quiet flag the following error is shown:
root#4d1b74229670:/# start-stop-daemon --stop --oknodo --retry TERM/10 --pidfile /var/run/slapd/slapd.pid --exec /usr/sbin/slapd
No /usr/sbin/slapd found running; none killed.
The /var/run/slapd/slapd.pid file exists, the /usr/sbin/slapd executable path is correct too and the process is visible like this:
root#4d1b74229670:/# ps -efww | grep slapd
openldap 764 1 0 20:13 ? 00:00:00 /usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d
root 779 1 0 20:22 pts/0 00:00:00 grep slapd
To work around this I changed the stop_slapd in /etc/init.d/slapd function and replaced --exec $SLAPD with --name slapd:
stop_slapd() {
reason="`start-stop-daemon --stop --quiet --oknodo --retry TERM/10 \
--pidfile "$SLAPD_PIDFILE" \
--name slapd 2>&1`"
}
I applied the change using sed:
sed -i 's/--exec $SLAPD 2/--name slapd 2/' /etc/init.d/slapd

This is another way to fix the issue:
SLAPD_PID=$(cat /run/slapd/slapd.pid)
kill -15 $SLAPD_PID
while [ -e /proc/$SLAPD_PID ]; do sleep 0.1; done # wait until slapd is terminated

Related

Running apache and cron in docker

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.

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

Can't start apache with supervisord from a Docker container

I'm running a Docker container with CoreOS which uses Debian latest as a base and has various packages installed including supervisor and apache2. I can start and successfully run apache using the following command:
# /usr/bin/pidproxy /var/run/apache2.pid /bin/bash -c "source /etc/apache2/envvars && /usr/sbin/apache2 -DFOREGROUND -k start"
However, when I stick this command in a supervisor config file:
[program:apache2]
command=/usr/bin/pidproxy /var/run/apache2.pid /bin/bash -c "source /etc/apache2/envvars && /usr/sbin/apache2 -DFOREGROUND -k start"
redirect_stderr=true
and do this:
# supervisorctl start apache2
I get back this response:
apache2: ERROR (abnormal termination)
Looking at the supervisor process log file I see the help output from the apache2 command, as if it had been called like so apache2 -h. I have no idea why a command which runs when executed on the command line as root (ssh into the container) would not work when verbatim executed by supervisorctl (run as root).
Any point in the right direction would be greatly appreciated.
Not really sure why, but adding quotes to my option values seems to have done the trick, and allowed me to use apachectl. Must be something with the context in which the command is interpreted, whatever supervisor is doing vs input from a bash prompt. Here's my working config file:
[program:apache2]
command=apachectl -D "FOREGROUND" -k start
redirect_stderr=true
You really want to use this. If you don't use pidproxy, a supervisorctl stop apache will not kill all it's children.
This will also make sure that the container will quit when it gets a SIGTERM instead of waiting for a SIGKILL.
[program:apache]
command=/usr/bin/pidproxy /var/run/apache2/apache2.pid /bin/bash -c "/usr/sbin/apache2ctl -D FOREGROUND"
autorestart=true
This is what works for me (using an ubuntu base image, but that should not matter):
Dockerfile:
# Pull Ubuntu as base image
FROM dockerfile/ubuntu
...
# Install supervisor to allow starting mutliple processes
RUN apt-get -y install supervisor && \
mkdir -p /var/log/supervisor && \
mkdir -p /etc/supervisor/conf.d
RUN mkdir /var/log/supervisord
# Add supervisor configuration
ADD etc/supervisor/supervisor.conf /etc/supervisor.conf
# Install Apache and enable CGI
RUN apt-get install -y apache2
ADD etc/apache/000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2enmod cgi
....
supervisor.conf
[supervisord]
; supervisord log file
logfile=/var/log/supervisord/supervisord.log
; info, debug, warn, trace
loglevel=debug
; pidfile location
pidfile=/var/run/supervisord.pid
; run supervisord as a daemon
nodaemon=false
; number of startup file descriptors
minfds=1024
; number of process descriptors
minprocs=200
; default user
user=root
; where child log files will live
childlogdir=/var/log/supervisord/
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
; Apache server
[program:apache2]
command=/usr/sbin/apache2ctl -D FOREGROUND
environment=APACHE_LOG_DIR=/var/log/apache2
redirect_stderr=true
In CentOS apache is Called httpd not apache2
Your supervisor conf file will need to be updated for CentOS
/usr/sbin/httpd is the program location.
[program:apache2]
command=/usr/bin/pidproxy /var/run/httpd.pid /bin/bash -c "/usr/sbin/httpd -DFOREGROUND -k start"
redirect_stderr=true

docker rabbitmq hostname issue

I am build an image using Dockerfile, and I would like to add users to RabbitMQ right after installation. The problem is that during build hostname of the docker container is different from when I run the resultant image. RabbitMQ loses that user; because of changed hostname it uses another DB.
I connot change /etc/hosts and /etc/hostname files from inside a container, and looks that RabbitMQ is not picking my changes to RABBITMQ_NODENAME and HOSTNAME variables.
The only thing that I found working is running this before starting RabbitMQ broker:
echo "NODENAME=rabbit#localhost" >> /etc/rabbitmq/rabbitmq.conf.d/ewos.conf
But then I will have to run docker image with changed hostname all the time.
docker run -h="localhost" image
Any ideas on what can be done? Maybe the solution is to add users to RabbitMQ not on build but on image run?
Just here is example how to configure from Dockerfile properly:
ENV HOSTNAME localhost
RUN /etc/init.d/rabbitmq-server start ; rabbitmqctl add_vhost /test; /etc/init.d/rabbitmq-server stop
This is remember your config.
Yes, I would suggest to add users when the container runs for the first time.
Instead of starting RabbitMQ directly, you can run a wrapper script that will take care of all the setup, and then start RabbitMQ. If the last step of the wrapper script is a process start, remember that you can use exec so that the new process replaces the script itself.
This is how I did it.
Dockerfile
FROM debian:jessie
MAINTAINER Francesco Casula <fra.casula#gmail.com>
VOLUME ["/var/www"]
WORKDIR /var/www
ENV HOSTNAME my-docker
ENV RABBITMQ_NODENAME rabbit#my-docker
COPY scripts /root/scripts
RUN /bin/bash /root/scripts/os-setup.bash && \
/bin/bash /root/scripts/install-rabbitmq.bash
CMD /etc/init.d/rabbitmq-server start && \
/bin/bash
os-setup.bash
#!/bin/bash
echo "127.0.0.1 localhost" > /etc/hosts
echo "127.0.1.1 my-docker" >> /etc/hosts
echo "my-docker" > /etc/hostname
install-rabbitmq.bash
#!/bin/bash
echo "NODENAME=rabbit#my-docker" > /etc/rabbitmq/rabbitmq-env.conf
echo 'deb http://www.rabbitmq.com/debian/ testing main' | tee /etc/apt/sources.list.d/rabbitmq.list
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | apt-key add -
apt-get update
cd ~
wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server_3.6.5-1_all.deb
dpkg -i rabbitmq-server_3.6.5-1_all.deb
apt-get install -f -y
/etc/init.d/rabbitmq-server start
sleep 3
rabbitmq-plugins enable amqp_client mochiweb rabbitmq_management rabbitmq_management_agent \
rabbitmq_management_visualiser rabbitmq_web_dispatch webmachine
rabbitmqctl delete_user guest
rabbitmqctl add_user bunny password
rabbitmqctl set_user_tags bunny administrator
rabbitmqctl delete_vhost /
rabbitmqctl add_vhost symfony_prod
rabbitmqctl set_permissions -p symfony_prod bunny ".*" ".*" ".*"
rabbitmqctl add_vhost symfony_dev
rabbitmqctl set_permissions -p symfony_dev bunny ".*" ".*" ".*"
rabbitmqctl add_vhost symfony_test
rabbitmqctl set_permissions -p symfony_test bunny ".*" ".*" ".*"
/etc/init.d/rabbitmq-server restart
IS_RABBIT_INSTALLED=`rabbitmqctl status | grep RabbitMQ | grep "3\.6\.5" | wc -l`
if [ "$IS_RABBIT_INSTALLED" = "0" ]; then
exit 1
fi
IS_RABBIT_CONFIGURED=`rabbitmqctl list_users | grep bunny | grep "administrator" | wc -l`
if [ "$IS_RABBIT_CONFIGURED" = "0" ]; then
exit 1
fi
Don't forget to run the container by specifying the right host with the -h flag:
docker run -h my-docker -it --name=my-docker -v $(pwd)/htdocs:/var/www my-docker
The only thing that helped me was to change default value in rabbitmq-env.conf of MNESIA_BASE property to MNESIA_BASE=/data and I added this command RUN mkdir /data in Dockerfile before starting server and add users.