Starting a service inside of a Dockerfile - apache

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.

Related

Why Molecule is not able to start a docker container (Failed to create temporary directory)

I found similar case here, that I am using molecule to test my ansible roles, but for some reason it is skipping "creation" part and gives error like:
fatal: [rabbitmq]: UNREACHABLE! => {"changed": false, "msg": "Failed to create temporary directory.In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\", for more error information use -vvv. Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp `\"&& mkdir \"` echo ~/.ansible/tmp/ansible-tmp-1638541586.6239848-828-250053975102429 `\" && echo ansible-tmp-1638541586.6239848-828-250053975102429=\"` echo ~/.ansible/tmp/ansible-tmp-1638541586.6239848-828-250053975102429 `\" ), exited with result 1", "unreachable": true}
It is skipping the create process: Skipping, instances already created. However, nothing is running:
name#EEW00438:~/.cache$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
name#EEW00438:~/.cache$
what I tried:
molecule destroy
molecule reset
restart
rm -rf ~/.cache/
changed remote_tmp to /tmp/.ansible/ in /etc/ansible/ansible.cfg
reinstall molecule
This issue is only with one role.
UPDATE:
it is failing on step:
mkdir \"` echo ~/.ansible/tmp/ansible-tmp-1638782939.31706-2913-12516475286623 `\" && echo ansible-tmp-1638782939.31706-2913-12516475286623=
mkdir: cannot create directory ‘"/home/user/.ansible/tmp/ansible-tmp-1638782939.31706-2913-12516475286623"’: No such file or directory
I stumbled upon this issue as well.
When you create the role you need to create it as molecule init role --driver-name docker ns.myrole to enable docker. Be sure to install the docker driver too if you haven't pip install --upgrade molecule-docker
So if you need to tweak the container that runs, edit molecule.yml. It defaults to centos. I switched to ubuntu in there, an created a Dockerfile to provision the container with things that need to exist.
molecule.yml
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: ubuntu:22.04 # this is required but ignored since I specify a `dockerfile`
pre_build_image: false
dockerfile: Dockerfile
provisioner:
name: ansible
verifier:
name: ansible
For example, Ubuntu 22.04 doesn't use python anymore, so I added an alias at the end of what molecule renders so that Ansible can use python and have it redirect to python3
FROM ubuntu:22.04
RUN if [ $(command -v apt-get) ]; then export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y python3 sudo bash ca-certificates iproute2 python3-apt aptitude && apt-get clean && rm -rf /var/lib/apt/lists/*; \
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install /usr/bin/python3 /usr/bin/python3-config /usr/bin/dnf-3 sudo bash iproute && dnf clean all; \
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y /usr/bin/python /usr/bin/python2-config sudo yum-plugin-ovl bash iproute && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python3 sudo bash iproute2 && zypper clean -a; \
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python3 sudo bash ca-certificates; \
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python3 sudo bash ca-certificates iproute2 && xbps-remove -O; fi
RUN echo 'alias python=python3' >> ~/.bashrc
It's been years since I last used Molecule, and I must say... it's gone downhill. It used to be easy/clear/direct to get things working. Sigh. I guess I should stick to containers and force the migration off VMs sooner!
The problem may be caused by a Docker context change performed at the start of Docker Desktop. Despite this, Molecule does create a container, but in an inactive context.
At startup, Docker Desktop automatically switches the context from default to desktop-linux [1]. The active context determines which containers are available from CLI.
The context cannot be set in the molecule, i.e. the default context is always used to create containers [2].
$ molecule create --scenario-name test
... # The output with the error is skipped because it duplicates the output from the question
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker context ls
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
desktop-linux * moby unix:///home/bkarpov/.docker/desktop/docker.sock
$ docker context use default
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a71bfd28992f geerlingguy/docker-ubuntu2004-ansible "bash -c 'while true…" 5 minutes ago Up 5 minutes some-instance
$ molecule login --scenario-name test
INFO Running test > login
root#some-instance:/#
Solutions
Switch the context back to default manually
docker context use default
This solution is suitable for one-time execution, since the context will need to be switched every time Docker Desktop is started. Docker Desktop service will continue to work using the desktop-linux context.
Issue with the request to add context switching to Docker Desktop - https://github.com/docker/roadmap/issues/47
Stop Docker Desktop
systemctl --user stop docker-desktop
Stopping the Docker Desktop service will automatically switch to the default context.
Set DOCKER_CONTEXT so that Docker Desktop does not change the context in the current shell
export DOCKER_CONTEXT=default
systemctl --user restart docker-desktop
When stopping, the context returns to default, and when starting, it does not switch to desktop-linux.
References
https://docs.docker.com/desktop/install/ubuntu/#launch-docker-desktop
https://github.com/ansible-community/molecule-docker#faq

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.

Cant get a Docker image with apache to display the test webpage

I have a docker image where I have put apache. I want it to that when the container starts, apache starts and I can visit the test page. However, the page is not appearing when I try.
This is my current dockerfile:
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"]
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
I am running the container with the command docker run -d -P <container_name>, and when I do docker ps, I see the ports section being populated correctly, with 0.0.0.0:32784->80/tcp, 0.0.0.0:32783->443/tcp as the output.
The url im trying to use to access it is 172.17.0.2:32784.
Any ideas?
Turns out the issue was that I was trying to connect with the docker containers IP, when the IP I shouldve been connecting with the IP of the server that it was hosted on.
Derp.

"no such file or directory" when running Docker image

I'm new to Docker and trying to create an image with owncloud 7 on centos 6.
I've created a Dockerfile. I've built an image.
Everything goes right except that when I run the image :
docker run -i -t -d -p 80:80 vfoury/owncloud7:v3
I get the error :
Cannot start container a7efd9be6a225c19089a0f5a5c92f53c4dd1887e8cf26277d3289936e0133c69:
exec: "/etc/init.d/mysqld start && /etc/init.d/httpd start":
stat /etc/init.d/mysqld start && /etc/init.d/httpd start: no such file or directory
If I run the image with /bin/bash
docker run -i -t -p 80:80 vfoury/owncloud7:v3 /bin/bash
then I can run the command
/etc/init.d/mysqld start && /etc/init.d/httpd start
and it works.
Here is my Dockerfile content :
# use the centos6 base image
FROM centos:centos6
MAINTAINER Vincent Foury
RUN yum -y update
# Install SSH server
RUN yum install -y openssh-server
RUN mkdir -p /var/run/sshd
# add epel repository
RUN yum install epel-release -y
# install owncloud 7
RUN yum install owncloud -y
# Expose les ports 22 et 80 pour les rendre accessible depuis l'hote
EXPOSE 22 80
# Modif owncloud conf to allow any client to access
COPY owncloud.conf /etc/httpd/conf.d/owncloud.conf
# start httpd and mysql
CMD ["/etc/init.d/mysqld start && /etc/init.d/httpd start"]
Any help would be greatly appreciated
Vincent F.
After many tests, here is the Dockerfile that works to install ouwncloud (without MySQL):
# use the centos6 base image
FROM centos:centos6
RUN yum -y update
# add epel repository
RUN yum install epel-release -y
# install owncloud 7
RUN yum install owncloud -y
EXPOSE 80
# Modif owncloud conf to allow any client to access
COPY owncloud.conf /etc/httpd/conf.d/owncloud.conf
# start httpd
CMD ["/usr/sbin/apachectl","-D","FOREGROUND"]
then
docker build -t <myname>/owncloud
then
docker run -i -t -p 80:80 -d <myname>/owncloud
then you should be able to open
http://localhost/owncloud
in your browser
I think this is because you're trying to use && within the Dockerfile CMD instruction.
If you intend to run multiple services within a Docker container, you may want to check Supervisor. It enables you to run multiple daemons within the container. Check the Docker documentation at https://docs.docker.com/articles/using_supervisord/.
Alternatively you could ADD a simple bash script to start the two daemons and then set the CMD to use the bash file you added.
The issue is that your CMD argument contains shell operations, but you're using the exec-form of CMD instead of the shell-form. The exec-form passes the arguments to one of the exec functions, which will not interpret the shell operations. The shell-form passes the arguments to sh -c.
Replace
CMD ["/etc/init.d/mysqld start && /etc/init.d/httpd start"]
with
CMD /etc/init.d/mysqld start && /etc/init.d/httpd start
or
CMD ["sh", "-c", "/etc/init.d/mysqld start && /etc/init.d/httpd start"]
See https://docs.docker.com/reference/builder/#cmd.