Docker compose and dockerfile / .htaccess problem - docker

Im few days in one project where I have a task of using Docker. After following few tutorials I find the easy way of deploying my LAMP server using docker-compose that looks like this:
version: '3.7'
services:
php-httpd:
image: php:7.3-apache
ports:
- 80:80
volumes:
- "./DocumentRoot:/var/www/html"
mariadb:
image: mariadb:10.5.2
volumes:
- mariadb-volume:/var/lib/mysql
environment:
TZ: "Europe/Rome"
MYSQL_ALLOW_EMPTY_PASSWORD: "no"
MYSQL_ROOT_PASSWORD: "rootpwd"
MYSQL_USER: 'testuser'
MYSQL_PASSWORD: 'testpassword'
MYSQL_DATABASE: 'testdb'
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- 'mariadb:db'
ports:
- 8081:80
volumes:
mariadb-volume:
Now after my app is in middle of development i find a problem that I need to edit the .htaccess to turn on mod_rewrite and add some rules for REST API.
All solutions that I find are mentioning that I should add RUN command in dockerfile similar to this:
FROM httpd:alpine
# Copy .htaccess into DocumentRoot
COPY ./.htaccess /var/www/html/
RUN sed -i '/LoadModule rewrite_module/s/^#//g' /usr/local/apache2/conf/httpd.conf
But I dont have that file, and offical documentation is of no help for me.
All I do is sudo docker-compose up -d to run my images. So question is:
In what stage, how and where should I add this file to make it work.
I know is possible cose I find this statement in one tutorial:
Next time around, we'll create a more complicated docker-compose.yml
file, one that works in conjunction with a Dockerfile.
But there was no followup on this.
I would appreciate any guidance on this.
Also I know I can access PHP image with: docker exec -it linuxconfig_php-httpd_1 bash.
Maybe I can do something with that?

You have two options:
Docker is a layered file system, You can use one image and make modifications to it to create another image, which you can then push to your private Docker Registry or public dockerhub. To, create a custom image with your .htaccess changes, you will create a file named "Dockerfile". You will then place the Dockerfile in the same directory where your modified .htaccess
Dockerfile content
FROM php:7.3-apache
RUN sed -i '/LoadModule rewrite_module/s/^#//g' /usr/local/apache2/conf/httpd.conf
Create Image:
docker build -t custom-php:7.3-apache .
This will create a new image name (custom-php:7.3-apache). You can then use this new image in your docker-compose.yml file and when deployed, the container will have the updated .htaccess
You may mount the .htaccess to the desired path by using volumes option as shown below
.
php-httpd:
image: php:7.3-apache
ports:
- 80:80
volumes:
- "./DocumentRoot:/var/www/html"
- "./.htaccess:/var/www/html/.htaccess"
I prefer #2 as you can edit .htaccess rules without rebuilding the image.

Related

Docker-Compose File

I have three seperate Microservices, and for each of them in their directory I have Dockerfile.
I am beginner in Docker and I am a little confused.
for define Docker Compose file, I must define three docker-compose.yml files in the directory of each services?!
Or I must define just one docker-compose.yml file for all my services?! If yes, in which directory?
Docker compose is built for having multiple apps, with a Dockerfile it is very powerful.
To put it simply you can split a docker-compose file into things called 'services' and they act as different, separate apps/microservices, so say I wanted a nodejs app and a database within the same docker-compose file and Dockerfile:
Dockerfile:
FROM node:7.7.2-alpine
WORKDIR /usr/app
COPY package.json .
RUN npm install --quiet
COPY . .
Docker-compose:
version: '3.1'
services:
mongo:
image: mongo
name: database
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
web:
build: .
command: npm run dev
volumes:
- .:/usr/app/
- /usr/app/node_modules
ports:
- "3000:3000"
depends_on:
- mongo
If you ran that in the directory you want to work at, it will always stay in that directory . You can name each service it's own name. This example it's mongo and web. Once running, locally you can reference and connect to your services just by using their respective names.
I recommend these two YouTube video. Quick and simple. Here and here
You don't need to create separate compose file. Docker compose provides you the option to specify the location of Dockerfiles in order to setup the containers. In the root folder which contains this three app create a compose file.
For an example check this file https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/docker-compose.yml

Why docker container can't see volume on different container?

I have 2 containers that I fire up using docker-compose up.
The first I just pull from the docker hub nginx:stable
The second one I build on top of the php from the hub
dockerfile
FROM composer:1.9.3
RUN mkdir /fatfree
RUN ["composer","require","bcosca/fatfree-core","--working-dir","/fatfree"]
FROM php:7.4-fpm
COPY --from=0 /fatfree /fatfree
I also tried VOLUME /fatfree in the above file to no avail.
docker-compose.yml
version: "3.7"
services:
webserver:
image: nginx:stable
ports:
- "80:8080"
volumes:
- ./www:/www
- fatfree:/fatfree
links:
- php
php:
build:
context: .
dockerfile: dockerfile
volumes:
- ./www:/www
- "fatfree:/fatfree"
volumes:
fatfree:
If I interpreted correctly the docker documentation, my www/index.php should be able to see whatever is in /fatfree, but it doesn't. The folder itself shows up, but it appears empty.
If I run the dockerfile interactively docker container run -i -t test bash , the /fatfree folder exists and it has all the files I expect it to have.
There are plenty of stackoverflow questions asking how to achieve this, and they all seem to suggest that what I'm doing is actually ok, but it doesn't work, and I have no clue why.
Any suggestion is appreciated.
Your mapping is incorrect.
You want:
volumes:
- /fatfree:/www
The first entry /fatfree refers to the path on your host machine.
The second entry /www refers to the path in the container.
In my example, your host's /fatfree directory (and content) will be mapped to the container's /www directory.
Change as desired.

Deploy with docker-compose.yml

Not sure if it will be a duplicate question but i tried to find out stuff but not sure if i have similar situation like others.
So i am new to docker and trying to setup a deployment for a small website.
So far i have a folder which has 3 files.
index.html - has basic html
Dockerfile - which has
FROM ubuntu:16.04
COPY . /var/www/html/
docker-compose.yml - which has
version: '2.1'
services:
app:
build: .
image: myname/myapp:1.0.0
nginx:
image: nginx
container_name: nginx
volumes:
- ./host-volumes:/cont-volumes
network_mode: "host"
phpfpm56:
image: php-fpm:5.6
container_name: phpfpm56
volumes:
- ./host-volumes:/cont-volumes
network_mode: "host"
mysql:
image: mysql:5.7
container_name: mysql
ports:
- "3306:3306"
volumes:
- mysql:/var/lib/mysql
volumes:
mysql:
Now i am using jenkins to create build, putting my all codes to host volumes to make it available to container and then i would run
docker-compose build
Now it creates an image and i push it to docker hub.
Then i login to remote server and pull the image and run. But that wont work because i still need to run docker-compose up inside the container.
Is this the right approach or i am missing something here?
The standard way to do this is to copy your code into the image. Do not bind-mount host folders containing your code; instead, use a Dockerfile COPY directive to copy in the application code (and in a compiled language, use a RUN command to build it). For example, your PHP container might have a corresponding Dockerfile that looks like (referencing this base Dockerfile)
FROM php-fpm:5.6
# Base Dockerfile defines a sensible WORKDIR
COPY . .
# Base Dockerfile sets EXPOSE 9000
# Base Dockerfile defines ENTRYPOINT, CMD
Then your docker-compose.yml would say, in part
version: '3'
service:
phpfpm56:
build: .
image: me/phpfpm56:2019-04-30
# No other settings
And then your nginx configuration would say, in part (using the Docker Compose service name as a hostname)
fastcgi_pass phpfpm56:9000
If you use this in production you need to comment out the build: lines I think.
If you're extremely set on a workflow where there is no hostname other than localhost and you do not need to rebuild Docker images to update code, you at least need to restart (some of) your containers after you've done the code push.
docker-compose stop app phpfpm56
docker-compose up -d
You might look into a system-automation tool like Ansible or Chef to automate the code-push mechanism. Those same tools can also just install nginx and PHP, and if you're trying to avoid the Docker image build sequence, you might have a simpler installation and deployment system running servers directly on the host.
docker-compose up should not be run inside a container but on a docker host. So this could be run via sh on a host but you need to have access to the composefile wherever you run the command.

Building and uploading images to Docker Hub, how to from Docker Compose?

I have been working in a docker environment for PHP development and finally I get it working as I need. This environment relies on docker-compose and the config looks like:
version: '2'
services:
php-apache:
env_file:
- dev_variables.env
image: reynierpm/php55-dev
build:
context: .
args:
- PUID=1000
- PGID=1000
ports:
- "80:80"
extra_hosts:
- "dockerhost:xxx.xxx.xxx.xxx"
volumes:
- ~/var/www:/var/www
There are some configurations like extra_hosts and env-file that is giving me some headache. Why? Because I don't know if the image will works under such circumstances.
Let's said:
I have run docker-compose up -d and the image reynierpm/php55-dev with tag latest has been built
I have everything working as it should be because I am setting the proper values on the docker-compose.yml file
I have logged in into my account and I push the image to the repository: docker push reynierpm/php55-dev
What happen if tomorrow you clone the repository and try to run docker-compose up but changing the docker-compose.yml file to fit your settings? How the image behaves in this case? I mean makes sense to create/upload the image to Docker Hub if any time I run the command docker-compose up it will be build again due to the changes on the config file?
Maybe I am completing wrong and some magic happen behind scenes but I need to know if I am doing this right
If people clone your git repository and do a docker-compose up -d it will in fact building a new image. If you only want people use your image from docker hub, drop the build section of docker-compose.yml and publish it in your docker hub page. Check this you can see the proposed docker-compose.yml.
Just paste this in your page:
version: '2'
services:
php-apache:
image: reynierpm/php55-dev
ports:
- "80:80"
environment:
DOCKERHOST: 'yourhostip'
PHP_ERROR_REPORTING: 'E_ALL & ~E_DEPRECATED & ~E_NOTICE'
volumes:
- ~/var/www:/var/www
If your env_file just have a couple of variables it is better to show them directly in the Dockerfile. It is better to replace extra_hosts with an environment variable and change in your php.ini or where ever you use the extra host by the variable:
.....
xdebug.remote_host = ${DOCKERHOST}
.....
You can in your Dockerfile define a default value for this variable:
ENV DOCKERHOST=localhost
Hope it helps
Regards

Docker ADD folder during build and then expose to VOLUME

I am using docker-compose for a basic web app. When the image is built, it copies the static JS files in (ADD) and then builds them.
I then want to expose that directory to other containers, using VOLUME.
E.g.
Dockerfile
ADD ./site/static /site/static
WORKDIR /site/static
RUN gulp
docker-compose.yml
app:
build: .
volumes:
- /site/static
http:
image: nginx
volumes_from:
- app
nginx.conf
location /static {
alias /site/static
}
(Note, this is just an example)
The problem is that it seems to work the first time (i.e. when the volume does not exist), but is then never overwritten by the modified image. If I was using purely a Dockerfile, I could achieve this by putting VOLUME after ADD.
Is there a way to allow this, or am I approaching it completely wrong?
Thanks
Possible solution 1
I might be wrong, but I think the trouble is that when (and if) you do
docker-compose down && docker-compose up
your containers are recreated, and new "anonymous" volume is created.
You can check my guess running:
docker volume ls
I would try to use named volume, like so:
version: "2"
volumes:
app-volume: ~
services:
app:
build: .
volumes:
- app-volume:/site/static
http:
image: nginx
volumes:
- app-volume:/site/static
You need docker-compose 1.6.0+ and require a Docker Engine of version 1.10.0+ for usinng version 2 of docker-compose file.
Possible solution 2
just
app:
build: .
volumes:
- ./site/static:/site/static # maps host directory `./site/static` (relative to docker-compose.yml) to /site/static inside container
http:
image: nginx
volumes_from:
- app
And remove
ADD ./site/static /site/static
from your Dockerfile

Resources