Docker is the famous 🐳 whale container.
A container is a all-packed-in-one system than can run on your machine while being entirely independent from it.
You can have python2 installed on your machine, and python3 installed in a container; you can have a machine that runs on ubuntu, and a container that runs on arch. And it’s all perfectly fine.
Containers allow us to create tailor-made environment for our applications without interfering with the machine environment.
For this project, we are asked to use a folder
srcs and a Dockerfile:
The dockerfile is like a makefile.
We could draw a simple comparison.
Dockerfile | Makefile
docker build . | make
image_id | a.out
docker run image_id | ./a.out
The dockerfile is then a set of instructions that builds up an environment with exactly what you need for your program to run, including specific library version, for example.
A few simple preliminary rules:
- Don’t use sudo statements in your dockerfile
- Don’t use . to indicate the current working directory, use ./ instead
- To chain lines use \
- A dockerfile has one and only one CMD statement
- Use COPY to move files from outside the container into the container
- Use RUN to run bash scripts inside the container
Now, the subject ft_server wants us to build a container with
- a debian buster OS
- nginx server
- mySQL database
- phpmyadmin service
- wordpress service
Docker works from images.
To get the image of debian buster, we’ll start off writing our dockerfile in the following way:
The : format indicates the version (or tag) of the image you need.
Now we can proceed — our Dockerfile will be divided into:
- part1, installations
- part2, configuration
- part3, permissions (grant rights to user)
[PART 1 : INSTALLATIONS]
For more about installations, check out this link.
RUN apt-get -y update
RUN apt-get -y install nginx \
php-fpm php-mysql \
wget dialog apt-utils \
php php-cgi php-mysqli php-pear php-mbstring php-gettext php-common php-phpseclib php-mysql
[PART 2 : CONFIGURATIONS]
Set the working directory for your server.
Make sure you have you config files saved in the srcs folder.
Let’ start with nginx.
COPY srcs/nginx.config /etc/nginx/sites-available/ RUN ln -s /etc/nginx/sites-available/nginx.config /etc/nginx/sites-enabled/
We COPY the config from srcs into the container, in a folder of our choice.
Then we RUN a command, in this case we create a symbolic link from sites-available to sites-enabled.
We need to do this for all config files in the right folder, for all the services we have.
I’ll let you work out the setup for phpnymadmin and wordpress.
When you’re done don’t forget to COPY.
COPY ./srcs/config.inc.php /var/www/myserver/phpmyadmin/ COPY ./srcs/wp-config.php /var/www/myserver/wordpress/
[PART 3 : PERMISSIONS]
We need now to grant permission to the user or we won’t have access to the folders’ content.
RUN chown -R www-data:www-data ../**/**
RUN chown -R 755 /var/www/myserver
RUN chmod -R 755 /var/www/*
and add the ssl certificate, fo C and ST you can of course switch to your country code and state.
RUN openssl req -x509 -nodes -days 365 -subj "/C=BE/ST=Belgium/L=your_city/O=your_building/OU=your_office/CN=your_name" -newkey rsa:2048 -keyout /etc/ssl/nginx-selfsigned.key -out /etc/ssl/nginx-selfsigned.crt;
A dockerfile should have only one CMD line, which is also the entry point of the container.
COPY ./srcs/init.sh ./
CMD /bin/bash ./init.shEXPOSE 80 443
The expose line doesn’t really do anything.
It only let people know on which ports you have configured your server — in our case, 80 for http and 443 for https.
So, what’s inside the init.sh?
service nginx start
service mysql start
service php7.3-fpm start
echo "CREATE DATABASE wordpress;"| mysql -u root --skip-password echo "GRANT ALL PRIVILEGES ON wordpress.* TO 'root'@'localhost' WITH GRANT OPTION;"| mysql -u root --skip-password echo "FLUSH PRIVILEGES;"| mysql -u root --skip-password echo "update mysql.user set plugin='' where user='root';"| mysql -u root --skip-password #sleep infinity & wait # option 1
bash # option 2
We start nginx, mysql, php.
We setup our mysql database (we create a user and a password — in our case, we opted for no password at all).
Now at the very bottom we have two ways of running our container.
Let’s see how they differ.
When our dockerfile is ready, we have to build our container with
docker build . and it will produce an image; you can also specify the name of your image if you want to, with
docker build -t a_name .
Once it’s built, you’ll see on your terminal:
Removing intermediate container c46df72a253f
Successfully built aa89aa05b6d1 # of course the id will be different
The last code we got is our image id that we need to run.
We can now run the container with
docker run -p 80:80 -p 443:443 image_id(don’t forget to always specify the -p port number).
But there is more, remember the two options?
With option 1
sleep infinity & wait :
We can run our container with a simple
Our docker container will continue run even after all processes have been run, literally forever. To exit it, open a new terminal tab and:
docker ps -a # to find the name of the running container
docker container stop container_name
With option 2
we will have to run the container with the -it flag,
docker run -it -p 80:80 -p 443:443 image_id . -it stands for interactive.
After running, you will land into the container bash terminal.
There you will be able to use all the shell commands, like ls, and navigate into your container.
To exit, type
exit or press ctrl+d.
[EXTRA : AUTOINDEX]
autoindex is what allows nginx to automatically find our website index.html page when we get on localhost. In nginx config you see a line that goes
autoindex: on . That’s the default — if you turn it off, localhost will throw an error, usually
403 Forbidden, and the page will be inaccessible.
You’ll need this script (don’t forget to COPY it):
sed -i “s/autoindex on;/autoindex off;/g” /etc/nginx/sites-available/nginx.config
service nginx restart
Now, how to run it?
If you are running your container with the -it flag, you’ll just need to do
bash myscript.sh in your container bash.
If you don’t use -it, while your container is running, you’ll have to open a new terminal tab and run:
docker run exec <container_name> bash /myscript.sh
Gals and guys, happy coding.