Docker for OJS: Blank page during the installation


I want to install ojs locally using docker and Ubuntu 20 as OS. I successed to get it run on Windows but some requirements pushs me to install it on Linux.
I just followed the instuctions described in this link .
After that I filled out the form as mentioned in the link, then after clicking on the install button, the displayed page is blank !
I’ve tried to track if there is a php error by consulting the “error.log” file but I didn’t find anything !
The version of ojs is 3_2_0-1.

Hello @anouar2002,

This recent post on the docker tool may be worth looking at: Docker for OJS: Geting DB errors when running official docker-compose on windows - #3 by anouar2002

Although, I think that some of the errors you are experiencing are different.

I’m also flagging @marc to potentially assist as well, as he has been one of the main persons behind the tool.

Best regards,

Public Knowledge Project Staff

Hello @rcgillis ,

Thanks for your reply. You advice to take a look at my post :slight_smile: .
If @marc has some free time, it will be great if he could help (I bothered him enough on the post of Windows).

The problem is now related to the OS, because the same steps work on Windows.



I bothered him enough on the post of Windows

No worry @anouar2002. :wink:
I’m happy to help and your feedback will let me improve the docker-ojs documentation… so take this as a synergy.

After that I filled out the form as mentioned in the link, then after clicking on the install button, the displayed page is blank! I’ve tried to track if there is a php error by consulting the “error.log” file but I didn’t find anything !

The “white screen of dead” (aka. WSOD) is a tricky problem to fix with web applications because it can be motivated by a lot of different issues (permissions, memory, db, network, configuration…). Basically first steep is finding any clue to discover what is hitting you so we can fix it.

Let’s start with the most probable so we can narrow it:

0) Check your containers…

First we need to be sure all goes well with docker. To check your containers, do:

$ docker-compose ps

That will return the status of your stack with something like follows:

  Name                    Command               State          Ports                   
ojs_app_demo   /usr/bin/supervisord -c /e ...   Up   >443/tcp,>80/tcp
ojs_db_demo mysqld      Up             3306/tcp      

Journal’s site in container’s names ("_demo") and ports app ports (8486 and 8081) may be different, but “Stat” need to be Up or something is wrong here.

1) Ensure you are checking the right logs…

In confidence I don’t remember if I redirected logs to stdout to let docker report about it but let’s try with this first. Go to the site folder and run:

$ docker-compose logs -f

Then refresh the web and see if you are getting something.
If not, press “Control+C” to finish and let’s check the regular logs inside the ojs_app container.
You can do it as follows:

$ docker exec -it ojs_app_demo tail -f /var/log/apache2/errors.log

May be is obvious but I assume here your container is called “ojs_app_demo” (that if I remember well is the default journal name) but check it and replace with the right name.

Again, in this case, the “-f” parameter will keep reading the file, so you can Alt+Tab and refresh your website with your WSOD. Then, go back to the terminal to see if you are getting something.

If not, don’t despair… we still have a third option to see what is happening behind this white screen and is making OJS more verbose in frontend.

2) How to make OJS more verbose.

To do this, you need to edit your and enable the following variables:

display_errors = On
debug = On

Modify the values or (if this is just for testing) add at the end of your config file.

I almost forget: You can edit you running container or edit your persistent config-file.

To edit your running container, you need go inside the container and then use vi or nano to edit the file, as follows:

$ docker exec -it ojs_app_demo tail -f /var/log/apache2/error.log

If you prefer editing your persistent config-file, you can use your favorite editor to edit this file:
"./volumes/config/" (from your site folder).

But and after this remember to restart the container to let docker re-read the permanent file, as follows:
$ docker-compose restart

Please, start with this and let’s see if we are lucky and we can get more info.

If all fails, we still have a few more options like the ones in this Drupal’s guide… or as you did before, you can upload a “tarball” :wink: of your site folder to let me take a look and check what happens.

Take care,

PD: If you want a shortcut… my guess this is an issue with DB credentials and OJS code can’t reach the database. :slight_smile:

Hello @marc ,
Thanks again for trying to help me. I really apperciate that. :heart_eyes:
Your answer is perfectly detailed but unfortunately I didn’t success to fix the issue.
FYI: I am using ubuntu 20 as virtual machine on my Windows (If this information may have an effect). I will explain it briefly below:
Solution 0):
My two containers have the up status as you can see on this screenshot:

Solution 1):
I’ve also tried but without any success, there is only a small difference, I don’t have the “php-errors.log” file, I have only the “error.log” which you used also in the point 2).
Anyway, I got a large list of logs but, te WSOD still persist.

Solution 2):
Here, I don’t really success to configure the config.ini.php because I didn’t find it :see_no_evil:
I followed the path given on the docker-compose.yml but there is only an index.html file which looks like:

I’ve also tried this command but nothing on the output.

I’ve created this tarball, you can check it :slight_smile:

Thanks in advance.


Thanks for the detailed feedback. It makes all easier.
Comments under your comments:

So looks like all is up and running in your port 8081.

BTW… are you checking the VM ip and not the host one, isn’t it?
Or are you running the browser inside the VM?
I mean, from your “regular” browser now localhost is your host, but the VM will have a different IP.

Sorry if the question looks silly, but is not easy to understand that to reach your final port now you have to go through 3 host (laptop > virtual machine > container).


  • If you are running the browser in the VM, we are fine with a simple “http://localhost:8081
  • If you are running the browser in the laptop, you will need to go to the VM ip (at 8081 port).

My bad. Old php errors where split. Fixed in former post for future readers (if any ;-))

Probably will be useless, but worth the shoot:

  • Do you mind to publish your large list of logs in pastebin or somewhere similar to take a look?

That’s fine. By default, docker-ojs will create a ./volumes/* empty structure to facilitate enable those volumes in future. But, to find errors is better check a vanilla installation (with no volumes).

Probably, once we make it run, you will like to create volumes (for your database files, uploads, and config). But forget about this till then.

The screen shoot confuses me. How do you reach this index.html?
This is supposed to be inside the container and the container don’t include any web browser…

If it’s your VM browser, thi is the “default” path for apache in your ubuntu machine (nothing related with the docker and our OJS).

If you remember what I said before about the 3 hosts (laptop > vm > container), as far as we don’t have volumes, we will like to go into the container and change the config files.

To do this you will need the terminal (inside the VM) and run:

$ docker exec -it ojs_app_demo tail -f /var/log/apache2/error.log

After this you will be inside the container (a new terminal) where you will be able to edit your OJS config file with vi or nano to modify “display_errors” and “debug” variables:

$ vi /var/www/html/

Alternatively, instead of forcing OJS to be more verbose, you can also check the logs inside the container running this in a terminal of your VM:

$ docker exec -it ojs_app_demo tail -f /var/log/apache2/error.log

This need to return something or we are missing something.

Take care,

Hello @marc,
Thanks again for your detailled answer and sorry for my late reply.

Yes I am running the browser inside the VM, so I am working completely inside the VM.

Of Course. Here is a link.

I was only following the path given in the docker-compose.yml file until I found the index.html file so I open it on the browser.

Ok I did that and the log in the pastbin link :slight_smile:


Hi @anouar2002

It’s ok as you did, but I need to explain that you can create all the pastebins you need.
For instance, if you create a different pastebin for each log the result will be easier to read. :wink:

If I didn’t miss something, looks like the result of “docker-compose logs” and “docker exec … error.log” is the same so, from now you can just check “docker-compose logs” that is more handy.

The logs is not complete, but the part I see is not a docker-specific issue. If I’m right (a second opinion is welcome), looks the OJS installation is not finish and is still trying to create a new user (called “anouar2002”) in a DB where this user exists:

[Tue Jan 19 16:39:16.823743 2021] [php7:error] [pid 73] [client] PHP Fatal error: Uncaught Exception: DB Error: Duplicate entry 'anouar2002' for key 'users_username' Query: INSERT INTO users\n\t\t\t\t(username, password, email, url, phone, mailing_address, billing_address, country, locales, date_last_email, date_registered, date_validated, date_last_login, must_change_password, disabled, disabled_reason, auth_id, auth_str, inline_help, gossip)\n\t\t\t\tVALUES\n\t\t\t\t(?, ?, ?, ?, ?, ?, ?, ?, ?, null, '2021-01-19 16:39:16', null, '2021-01-19 16:39:16', ?, ?, ?, ?, ?, ?, ?) in /var/www/html/lib/pkp/classes/db/\nStack trace:\n#0 /var/www/html/lib/pkp/classes/db/ DAO->handleError(Object(ADODB_mysqli), 'INSERT INTO use...')\n#1 /var/www/html/lib/pkp/classes/user/ DAO->update('INSERT INTO use...', Array)\n#2 /var/www/html/lib/pkp/classes/install/ UserDAO->insertObject(Object(User))\n#3 /var/www/html/lib/pkp/classes/install/ PKPInstall->createData(Object(Install), Array)\n#4 /var/www/html/lib/pkp/classes/install/Insta in /var/www/html/lib/pkp/classes/db/ on line 703, referer: http://localhost:8081/index/install

IMHO, the problem is motivated for an error during installation.
May be a first installation process was stop before it finished and then you start a second one?

As far you don’t have real data, the easier solution here would be reinstall it again.

With docker, as far as you don’t have volumes, it will be as easy as:

$ docker-compose stop
$ docker-compose rm
$ docker-compose up -d

(Well, you can do the same with a single “$ docker-compose up --force-recreate --renew-anon-volumes -d” command, but I prefer those 3 commands because is more clear what you are doing).

After this, you will be able to reach a brand new ojs in your http://localhost:8081.

Please, install it again with the data you have in your .env file.

IMPORTANT: Remember in docker volumes are not persistent (if you stop your docker engine, data will be lost), so once we ensure all works as expected, flag me and I will explain you how to create (at least) a volume for your DB and your upload files.


1 Like

Hi @marc,
Thank you for the quick reply! Yes the installation is successfully completed :partying_face:
The solution is as you suggested to reinstall ojs again.
I has this solution the hole of time in my head, but I didn’t try it because I has thoughts that it won’t bring anything :confused: I waste al ot of time on testing other methods!
Anyway, I am happy that is work and I can start creating some data :slight_smile: Thanks again !


I don’t want to sound like a fortune cookie, but don’t think in this like a waste of time because in the process you learned stuff to consolidate your docker and ojs knowledge and it save you to fall in same holes in future. :wink:

About starting create data, please don’t yet and read the next chapter of our book titled “Make your data persistent”.

As told, in docker, data is not persistent by default. One important idea behind docker is that is designed to left nothing behind, so in case something is wrong (sh-it happens) need to be extremely easy to go back to a former state of your machine.

It means, that now, your DB data [1], your uploaded files and your config file will disappear “like tears in the rain” when you stop your container.


How to make your data persistent?

Thinking in common usages, the docker-compose files we distribute include some comments thinking in usual scenarios. The volumes can be found in the “volumes” section of your docker-compose file and look like:

  - ./volumes/db:/var/lib/mysql

Left side tells docker where OUTSIDE the container (in your laptop) the volume will be stored (unsure if you will need to change slash in windows or they accept a common syntax). In this case is “./volumes/db” folder, that the distribution included empty for any project.

Right side tells docker where this data will be mapped INSIDE the container and as you see is the default folder for mysql/mariadb data storage.

Let’s say that you like to keep save your db files, your upload files and your ojs-config.

You can do it with this 3 simple steps:

  1. Stop your container.

    $ docker compose stop

  2. Edit your docker-compose.yml and uncomment the volume lines you like

  3. Restart your container.

    $ docker compose up -d

That’s all. Easy, isn’t it? :wink:

Well… in step 2, you need to be sure your OUTSIDE folders exist, but this is not a deal.

So, to keep persistent db, uploads (public and private files) and your config those will be the lines to uncomment:

24:    volumes:
25:      - ./volumes/db:/var/lib/mysql
43:    volumes:
44: #       - /etc/localtime:/etc/localtime
45:      - ./volumes/private:/srv/files
46:      - ./volumes/public:/var/www/html/public
47: #      - ./volumes/logs/app:/var/log/apache2
48:      - ./volumes/config/

We left some lines commented but feel free to play with them if you like to (for instance) see and keep your apache logs outside the container, create a new plugin (ie: mapping /var/www/html/plugins/general/yourTheme), or whatever… Notice you can also think in volumes as a door to your container and not only a way to ensure data will be persistent.

Volumes are thought to map folders, not files. So line 48 is a trick that need a replacement (I’m on it), but at this moment it works and is safe.
In the other hand, I need to recognize I’m a little unsure about if mysql data will disappear when you stop a container, because I think mysql image defines it as an anonymous volume, but anyway, it’s better create a volume to be sure your data is safe and to know where is stored.

I think that’s all. Please try it and tell me how it goes.


Hello @marc,

Yes, you are right, I just was saying why I didn’t try to reinstall the docker. Anyway, as you said, I learned some other practices and stuffs :slight_smile:

Yes, it looks too easy but for me wasn’t the case :confused:
Step 2 caused some problems. I was always afraid to change an yml file, you know, a not needed space can corrupt everything !
After uncommenting the lines as you described (I uncommented the same lines as you, I didn’t want to take a risk as first step), I have to add a space after each modified line in order to keep them aligned as before, but I receive this error:
After that, I removed the spaces and I let it looks like your screenshot, but also I received this error:

I am not sure if the folder exists or not, or it is another problem ?


Hi @anouar2002

I missed to say in former posts that, to make it easier to cut&paste and to search, please paste text instead of images. If the text is short (1-10 lines) use “peformated text” button. Otherwise, use pastebin.

I was always afraid to change an yml file, you know, a not needed space can corrupt everything !

Yes, you are right. YML is an invention of the devil. :frowning:
It’s really easy to miss an space as it happen in your fist screenshoot.

My suggestion for this would be configure your editor to show the spaces and double check your editions. A good editor is essential.

There is also a docker-compose command that will let you check without running anything, that is:

$ docker-compose config

If you get a “parsed” version of your docker-compose.yml it means you are safe.
If there is any error, you can check it with the peace of mind that you are not running your containers yet.

About your second screenshoot, we don’t need to worry about the warnings (just telling that docker is going to recycle existing volumes) but I’m a little bit more worried about the ERRORS.

My suggestion is “comment” the line in volumes, delete all volumes and restart the process again.

You can do it as follows:

  1. edit and comment line 48 with: # - ./volumes/config/
  2. Remove former volumes with:
docker volume ls     # to list all the existing volumes
docker volume rm volume_name1 volume_name2 ...

You are supposed to be able to do the same with docker-compose down -v, but I can tell for sure.
Use any of both but after this, doublecheck again with “docker volume ls” to be sure you deleted all the attached volumes.

After this you are safe and clean and you can start a new installation (last one :wink:) that, in this case, will create persistent volumes for db and uploads.

The only missing stuff will be but we can deal with this after.


1 Like

Hi @marc,

Oh Sorry, my fault. I didn’t think that you will maybe copy&paste it.

Thanks ! this is really helpful :slight_smile:

Oh we have a problem here, I forget to tell you that besides OJS, I am installing two other plateforms: ORKG and stencila, they have also some running volumes which I cannot identify it (Although I ran the command inside the ojs folder):

root@anouar:/home/anouar/Downloads/docker-ojs-master/versions/3_2_0-1/alpine/apache/php73# docker volume ls
local               0e567c21b266163c2c06031a1f13e0359bb5bd537918531097dec8f4512fa00c
local               1d5ae453b289c34b38b4624467f67a7376ad65b6d23f8e7d3068fd0a1b86aceb
local               2b257210a2a41d4a53dcedf1f6a9e0975b137076a418349df60ad3cfb1b9da8e
local               6afd71a3bf5119732074626b68299063aea6c662ea35d4e59bb2330eadffd144
local               9d90fbcdcb93f92d5b400067f0a79fc4a8fe04972dd5c6aa7ad324344b16f522
local               44ca6040f9c208e464667be26fba25e09483efc49b8c0ccc01782599bb365c15
local               073cca258215d442f2ef5131535164fab220c87d4327d4758925cc735d8ad870
local               5327e9c657a1dd1b8fab1216c4b92885a1e7f57784a0406bd0550110cc4f372c
local               65751b7a030e32b25c3c1989f2c8a5f43100b47a3d762b7a5b24faa6821189b5
local               68977d1fb8e5331a6f4093862abcbdb20e40624a178a7ff915c11a76ccddc659
local               84841bf96667a57267049629af2c89c51eb4b2ba2e7514876dc15d53d614a494
local               0326594f501285ea528cf422709ca54baf108f28afd0700e7226915268107eea
local               659670357c078ad8309a47017dde6293fa60e6e61a303599322ebc3c49a5036d
local               a9727b754703bb15cd829d224a281053cba4cba16472ed28194aa32700ef26f3
local               acf0cf6104a851ca38bb47596f92ce3ca07d9880806d3c627f24d8058345b4ad
local               b1f88428296f6cd7d55657deb00bd5746be1cd3175ee9f57c40a28d0722b49ef
local               c4b4e240e069801007866170d31784ca91916c45b2a642c7e2d3fae4f48bd5c1
local               d04e21aa94f567cfd94d596577b8014982fd78c6a0d2b4bc656b8082ce2d81f3
local               dfaad7300d2272c56b7f982480730b993eaeabcdfcb33ba1d9da118697789ba0
local               ead5e162e09eef373bd7501c6219880ba7052ce3a12d0e14cceaa6ca3a0414c3
local               hub_broker
local               hub_monitor
local               orkg-backend-master_neo4j-data
local               orkg-backend-master_postgres-data

The last fouth volumes doesn’t belong to OJS. I have only doubt on the rest because they are given in hexadecimal form.
If you have maybe idea which one are the OJS volumes, or I have to delete it all and then reinstall all the plateforms :slight_smile:


Looks like images with “named volumes” would be a nice improvement. Adding this to my toDo list.

About your question, docker desktop will probably have an option to explore this, but there is no desktop for linux so I can’ tell for sure. Anyway, you can try this command that will throw a complete list of containers and bound volumes:

$ docker ps -a --format '{{ .ID }}' | xargs -I {} docker inspect -f '{{ .Name }}{{ printf "\n" }}{{ range .Mounts }}{{ printf "\n\t" }}{{ .Type }} {{ if eq .Type "bind" }}{{ .Source }}{{ end }}{{ .Name }} => {{ .Destination }}{{ end }}{{ printf "\n" }}' {} | more

If you want a GUI able to run on every OS, I recommend portainer.
Here you have a guide to install it:


1 Like

Hello @marc,
Thanks again for your support. Unfortunately, this problem is not easy to resolve as we thought.
The command that you give help me to identify the volumes of OJS as shown in this pastbin

So if I have right, the first five volumes (until /blissful_kapitsa) belong to OJS.
The problem now that I cannot remove these volumes because they are in use. Also -f to force the removing doesn’t resolve the problem as you can see here:

        root@anouar:/home/anouar/Downloads/docker-ojs-master/versions/3_2_0-1/alpine/apache/php73# docker volume rm -f 9d90fbcdcb93f92d5b400067f0a79fc4a8fe04972dd5c6aa7ad324344b16f522
        Error response from daemon: remove 9d90fbcdcb93f92d5b400067f0a79fc4a8fe04972dd5c6aa7ad324344b16f522: volume is in use - [0664aecf7a79cec18c47bc1a5bca24918a6a1974c92d2d00c5632ef291a719ed]

Thanks, this can be a good alternative if we can’t identify the volumes :slight_smile:


Hi @anouar2002 ,

Try installing portainer if you like (in linux you can deploy a portainer with docker with two simple lines, so may be you can do it in your VM?) but with the output you publish and the error returned in former message you have all the needed elements to fix it.

Baby steps…

1) What is the error telling us?

Let me replace IDs by tags to make it more clear:

Error response from daemon: remove <volumeID>: volume is in use - [<containerID]

So, what is telling us is “you can not remove volume with ID 16f522” because “your container ID 1a719ed is still using it” and if you do, bad things will happen to the container, so docker is protecting you from this potential harmful action.

2) Solution? Stop or remove the container

Docker output returns you the container ID but if you prefer names working with names, you just need to check the output of the former command (the one you uploaded to pastebin) that tells us the owner of this volume is container “ojs_db_journal”.

Now, you only need to stop the container with any of those two commands:

$ docker stop ojs_db_journal
$ docker stop 0664aecf7a79cec18c47bc1a5bca24918a6a1974c92d2d00c5632ef291a719ed

Or better than that, go to the “journal” site and run a simple “docker-compose stop” that will stop all the stack (ojs_db_journal and ojs_app_journal).

After this, you will be able to remove your volume without any complain from docker.


1 Like

Hello @marc,
Sorry for the late answer, I was trying and trying because I didn’t want to answer you and reclaim another problem but it seems the case :confused:

Thank for recommending me portainer, I install it as described in documentation but I got some errors, I think he uses the same port as one of the platform that I install it. Anyway, I didn’t waste a lot of time on resolving this problem, because, in term of priority, getting OJS works with persistent data is more important now for me and I have to prepare some examples of data before Wednesday :cold_sweat:

Thanks this works perfectly :clap:
The problem now is by the new installation, it comes the error of "The public files directory does not exist or is not writable. "
Let us check what I made exactly:

==> Done

==> Done

The error persist here "The public files directory does not exist or is not writable. "


I have to prepare some examples of data before Wednesday.

Wow… Didn’t know you had a deadline so close. :frowning:

The public files directory does not exist or is not writable. "

That’s good. It means that docker is working fine and now the problem is in the installation side.

Take a look to your docker-compose.yml and the public folder mapping:

45:      - ./volumes/private:/srv/files
46:      - ./volumes/public:/var/www/html/public

In this example I will need to fill the OJS installation form with /var/www/html/public for the public folder and /srv/files for the private one.

Sometimes you can also get this issue with the wrong folder permissions in your volumes, so docker can write in the public or private folders. As we are in a hurry, set the public and private folders to 777 as follows.

$ chmod 777 ./volumes/public ./volumes/private

Take care,

1 Like

No worries, it is only the deadline for a first results demonstration, after the plateforms installation, my supervisor want to see some data and examples, the dealine of final project is the end of April.

Yes this is correct as described in my file.

This commande resolves the problem and now the installation is completed with succes, I have to check only if the data is persistent or no, to do that I need just to create an article for example, then stop the docker and start it again and see if the article exists ?


In our “docker tutorial by fascicles” today is time for some theory to understand the terminology and how all it works. :slight_smile:

Please, read this article:

So, after the reading you know we can have 3 types of volumes: Anonymous, Named and Sourced (or bind) volumes.

The ones we use in the ojs images are the third ones: bind volumes.

We like to use those ones because it will give you a clear view where your data is storage.
Volumes are relative to the project folder and it let you be sure you have all you need to run a docker-ojs there.

BTW, in former post I was suggesting an improvement and name volumes.
I forget why we didn’t named them, and is for a solid argument:


I think the only downside with bind volumes is that docker will store them with an absolute path (that it’s annoying to make stuff portable) but I prefer “see” where data is stored than leave it in docker hands.
Anyway, all is open to debate so we can move to a different approaches if it fits with everybody’s needs.

I have to check only if the data is persistent or no

The folders you map in your docker-compose ARE persistent.
If you like, you can go to your’s ./volumes/db and take a look to your database files or, once you upload some stuff, check your ./volumes/public or ./volumes/private.

to do that I need just to create an article for example, then stop the docker and start it again and see if the article exists ?

You don’t need but, for your pace of mind, I would do this as you said. :wink:
Now that you don’t have data, I will also run a “$ docker-compose rm” to let you be sure that you can not harm your persistent volumes.

1 Like