Need help finding correct path the the /bin/buildout

I successfully installed Plone 6.0 classic, I followed : Installation — Plone Documentation v5.2

Installed on umbuntu 20 .

I am comfortable running buildout (esp Plone 4); however, now i can't find the location of the Plone installation.

can someone help me out. i want to be able to install products and such

Thanks for your time.


1 Like

Did you install Plone 6.0 or Plone 5.1.6? Your screenshot shows a Plone-5.1.6-UnifiedInstaller directory.

Did you look under /opt/plone?

@mekell sorry, i should have been more clear:

  1. i did install 5.1.6 as you noted. However, this isn't what i'm working on. However, i did go to opt/plone and did find what i need for later, so thanks
  2. what i am looking for is help with Plone 6. I installed both Classic and Volt as two instances. I installed using containers per: the above and both work file. i have never used containers before and i don't know how to get to the familiar file structure.

attached shows what it looks like when i go into the "opt folder". there is a "containered" i trying drilling down into it. but i couldn't find anything i understood.

Call you help me figure our where the file structure is for Plone 6


The container(s) must be started to access them.

Here some useful commands when working with docker (see Docker command line reference):

  • List containers: sudo docker ps -a
  • Start container: sudo docker start CONTAINER:
  • Stop container: sudo docker stop CONTAINER
  • Execute interactive bash in container sudo docker exec -it CONTAINER bash

With sudo docker ps -a you'll get a list of the containers, something like the following:

CONTAINER ID   IMAGE                         COMMAND                  CREATED              STATUS                         PORTS                                       NAMES
66d51d86a01d   plone/plone-frontend:latest   "docker-entrypoint.s…"   8 seconds ago        Up 6 seconds        >3000/tcp, :::3000->3000/tcp   plone6-frontend
623d8dccf7b8   plone/plone-backend:6.0       "/app/docker-entrypo…"   About a minute ago   Up About a minute (healthy)>8080/tcp, :::8080->8080/tcp   plone6-backend

The last column (NAMES) is the CONTAINER name you put in the command (e.g. sudo docker start plone6-backend).

With sudo docker exec -it plone6-backend bash you enter an interactive bash in the container named plone6-backend. This works ofc only when the container has been started (with e.g. sudo docker start plone6-backend). Once in your container you are in the /app directory:

root@623d8dccf7b8:/app# ls
bin  etc  include  inituser  lib  lib64  pyvenv.cfg  scripts  var

root@623d8dccf7b8:/app# ls bin
Activate.ps1   diazopreprocessor  i18nextract     pip                   python3.11     zconfig_schema2html  zodbpack
__pycache__    diazorun           icalendar       pip3                  repozo             runwsgi         zconsole             zope-sendmail
activate       fsdump             jsonschema      pip3.11               roman  runzeo          zdaemon
activate.csh   fsoids             markdown_py     plone-register-flags       unidecode       zeo-nagios  fsrefs             mkwsgiinstance  plone-register-icons              waitress-serve  zeoctl
addzopeuser    fstail             normalizer      python                 wheel           zeopack
diazocompiler  futurize           pasteurize      python3                  zconfig         zodbconvert

root@623d8dccf7b8:/app# ls etc
package-includes  relstorage.conf  site.zcml  zeo.conf  zope.conf  zope.conf.d  zope.ini

PS: When I started to work with containers it helped me to think of a container as if it were kinda virtual machine that must be configured, started, stopped, accessed etc.

1 Like

@mekell Thanks for the detailed approach.
i followed it and i'm fine when i'm inside the old plone layout (I'll call that the "wget installation" method. i an do everything i want from there.
However, when I go inside Docker (as above - and see screen shot) I'm lost as how to get to the file structure I know.
Docker just seems so incredibly confusing. :frowning:

Thanks for continued help

@rileydog Things are definitely different in the Docker world!

Each container has its own filesystem. So paths like /app or /etc inside the container are in their own namespace, not the same as those paths on the host machine outside the container.

In general the same key files are there in the container as in the structure you're used to, but some of them are in different places (this is less a consequence of using Docker, and more a consequence of the fact that the Docker image installs Plone using pip instead of buildout). I can see from your screenshot that you found some things that should look familiar:

  • The filestorage and blobstorage in /app/var (note: it's possible to mount this directory from a folder on the host machine if you want the data to persist when you stop the container)
  • zope.conf and zope.ini in /app/etc

We can probably be more helpful if you can name specific things you're looking for but not finding.

The plone-backend Docker image does not use plonectl for controlling the instance. Zope is started when the container starts, using the script. This script also supports some other commands, like ./ run [path/to/] to run an instance script, and ./ console` to get a Python debug console.

In general with Docker logs go to stdout rather than to a file. Then you can view the logs from outside the container using the docker logs [container] command.

You don't have to use Docker, especially while developing. One option is to use GitHub - collective/cookiecutter-plone-starter: Cookiecutter Plone Starter is a framework for jumpstarting Plone 6 projects quickly. to create a project. It sets up a Makefile with commands to start the backend and frontend without using Docker, but it also comes with a Dockerfile that you can use to build an image for deployment. The non-Docker installation will still take a bit of getting used to though, because like I said, it no longer uses buildout.

1 Like

What I'm trying to do is add products. Is that still done by add them to the buildout file? if so, that is what i need to find. if not, then how do I add products


When installed with pip you don't use buildout. There is no buildout file needed.

Addons are also installed with pip, here is an example with plone.reload==3.0.2:

${PLONE_HOME}/bin/pip install plone.reload==3.0.2

Addons that are "editable" and in your local path (i.e. setuptools "develop mode") are also installed with pip but in "editable mode" with the option -e:

# create src directory for you addons
mkdir ${PLONE_HOME}/src
# create your addon directory struture and files in ${PLONE_HOME}/src
# install your addon with pip in editable mode (i.e. setuptools "develop mode")
${PLONE_HOME}/bin/pip install -e ${PLONE_HOME}/src/

I'd suggest to first get acquainted with the details of a pip installation (as different from a buildout installation) before you get confused by docker's specifics.

The following is a minimal pip installation of Plone 6 Classic UI which can help to get used with pip's installations:

# install packages
sudo apt-get install -y python3-venv
sudo apt-get install -y git
# set variables
# create venv
${PYTHON_TARGET_DIR}/python3 -m venv "${PLONE_HOME}"
# install pip setuptools and wheel
${PLONE_HOME}/bin/python -m pip install -U pip wheel setuptools -c ${PLONE_CONSTRAINTS}
# install Plone
${PLONE_HOME}/bin/pip --debug install Plone -c ${PLONE_CONSTRAINTS}
# install zope.mkzeoinstance and cookiecutter==2.1.1
${PLONE_HOME}/bin/pip install zope.mkzeoinstance -c ${PLONE_CONSTRAINTS}
${PLONE_HOME}/bin/pip install cookiecutter==2.1.1 -c ${PLONE_CONSTRAINTS}
# create zeoinstance with mkzeoinstance
${PLONE_HOME}/bin/mkzeoinstance zeoserver
# create zopeinstance (aka client) with cookiecutter using a yaml config file
cat <<EOF | tee ${PLONE_HOME}/client.yaml
    target: 'client'
    wsgi_listen: '*:8081'
    initial_user_name: 'admin'
    initial_user_password: 'secret'
    db_blobs_mode: 'shared'
    db_storage: 'zeo'
    db_zeo_server: ''
    db_zeo_read_only: false
    db_zeo_read_only_fallback: false
    db_blobs_location: "blobstorage"
${PLONE_HOME}/bin/cookiecutter \
    -f --no-input \
    --config-file "${PLONE_HOME}/client.yaml" \
    --checkout 1.0.0b2
# run zeo in background
${PLONE_HOME}/bin/runzeo -C ${PLONE_HOME}/zeoserver/etc/zeo.conf &
# run wsgi in background
${PLONE_HOME}/bin/runwsgi -v ${PLONE_HOME}/client/etc/zope.ini &
# alternatively run wsgi in debug mode
${PLONE_HOME}/bin/runwsgi -dv ${PLONE_HOME}/client/etc/zope.ini

The directory structures are as follows (The directories under "site-packages" are omitted)

After installing venv, pip, setuptools and wheel the directory structure is as follows:

├── bin
├── include
├── lib
│   └── python3.9
│       └── site-packages
│           └── ...
├── lib64 -> lib
└── share
    └── python-wheels

After pip installing Plone you get some header files for persistence and zope.proxy and more packages under "site-packages":

└── include
    └── site
        └── python3.9
            ├── persistent
            └── zope.proxy

after create zeoinstance with mkzeoinstance you get a directory called "zeoserver" (this can be defined in when calling "mkzeoinstance")

└── zeoserver
    ├── bin
    ├── etc
    ├── log
    └── var

after create zope instance with cookiecutter you get the directories "blobstorage" and "client" (the names can be defined in the yaml config-file passed to cookiecutter)

├── blobstorage
└── client
    ├── etc
    └── var
        ├── cache
        └── log

The complete final structure is something like:

├── bin
├── blobstorage
├── client
│   ├── etc
│   └── var
│       ├── cache
│       └── log
├── include
│   └── site
│       └── python3.9
│           ├── persistent
│           └── zope.proxy
├── lib
│   └── python3.9
│       └── site-packages
│           └── ...
├── lib64 -> lib
├── share
│   └── python-wheels
└── zeoserver
    ├── bin
    ├── etc
    ├── log
    └── var

When you compare this strucure with the one in docker (backend) they are similar. The main difference (as @davisagli explained above) are that the directories for zeo, zope, blobstorage, filestorage, log etc. have other names and are placed elsewhere. Here a docker backend directory structure to compare:

├── bin
├── etc
│   ├── package-includes
│   └── zope.conf.d
├── include
│   ├── python3.11
│   └── site
│       └── python3.11
│           ├── persistent
│           └── zope.proxy
├── lib
│   └── python3.11
│       └── site-packages
│           └── ...
├── lib64 -> lib  [recursive, not followed]
├── scripts
└── var -> /data
    ├── blobstorage
    ├── cache
    ├── filestorage
    └── log

I’m going to stick with containers as I already have this installed and working.

What you said above is making sense to me.


  1. I understand that Docker has it’s own commands for starting and stoping itself – and the software “inside” so I don’t need to use/be concerned about ZopeCtl.

  2. when i use the command "sudo docker exec -it plone6-backend bash

            I get:  root@8bdb82483500:/app#
  3. this makes complete sense to me:
    *8bdb82483500 is the container name for plone6-backend.
    *and I'm at the "root" of the plone6-backend

  4. I see the list of directories, and taking cue from you, I don’t assume they will have the same name/structure as what I am use to. So I open all the folders. i didn't see anything that made sense for my goal (adding products)

  5. i did see the Is this the key to the mystery?

What hangs me up:

can you give me very specific instructions on how to install a new product.

For example: Products.PloneKeywordManager

This is all I'm after.

Thanks for your help. I know you and all the others here volunteer here to answer this newbie questions.

1 Like

Did you try what I've explained above (Need help finding correct path the the /bin/buildout - #8 by mekell)?

Here the requested example:

Either from inside the container:

# execute interactive bash in container
user@debian11:~$ sudo docker exec -it CONTAINER bash
# once in the container pip install your product
root@8e6211328007:/app# bin/pip install Products.PloneKeywordManager
Successfully installed Products.PloneKeywordManager-6.0.0
# exit the container
root@8e6211328007:/app# exit
# restart the container
user@debian11:~$ sudo docker restart CONTAINER

or from outside the container:

# pip install your product from outside the container
user@debian11:~$ sudo docker exec CONTAINER bash -c 'bin/pip install Products.PloneKeywordManager'
Successfully installed Products.PloneKeywordManager-6.0.0
# restart the container
user@debian11:~$ sudo docker restart CONTAINER

or include add-ons during startup time in a container using the ADDON environment variable (see Documentation)

user@debian11:~$ sudo docker run \
        --name CONTAINER \
        -e SITE=Plone \
        -e ADDONS="Products.PloneKeywordManager" \
        -d \
        -p 8080:8080 \
1 Like

thank you!

I didn't catch on to your post above because i was too lost in the weeds.

I really appreciate your work and @davisagli

I will stick with using docker as my solution

Sorry, i hate coming back again.

I was installing Plone products (works slick). I installed about 5 products successfully, then i tried to install (it was on the list of products supposed to work in P6)

after installation i restarted - site won't open
when i look in Docker - now, the container plone6-end is gone
when I use ps -a the container is listed with "exited".

looking online i see this is a common issue; however, i can't find a solution that makes sense.

something obviously made Plone unhappy during the installation of - even though it reports back the it was installed.

How can I undo this?
As always, thanks for the help.

What do you mean "is gone"?

sudo docker ps shows just running containers. Use sudo docker ps -a to show all containers.

Look at the logs of the container with sudo docker logs CONTAINER to find out what went wrong.

Easy way (if you don't need forensics)

If this is a test container and has no data or configuration you want to save, simply stop and remove container.
Creating the container again is a matter of seconds because the image plone/plone-backend is already in your system and doesn't need to be downloaded again.

sudo docker stop CONTAINER
sudo docker rm  CONTAINER
# use your command and your options here to run a new container
sudo docker run  \
    --name CONTAINER \
    -e SITE=Plone \
    -d -p 8080:8080 \

Not that easy (if you want forensics)

Because containers are supposed to be immutable you can not do exec into a container which is stopped/exited. The container has to be running first.

You could commit the container to an image and run/start it using /bin/bash as entrypoint to start to find out what happened:

sudo docker commit CONTAINER user/myimage
sudo docker run --name mynewcontainer -ti --entrypoint=/bin/bash user/myimage
# here you are in mynewcontainer 
# if you need to enter the bash again do
sudo docker exec -it mynewcontainer bash

or more Plone specific:

# run in DEBUG_MODE
sudo docker run  \
    --name CONTAINER \
    -e SITE=Plone \
    -e DEBUG_MODE=on \
    -d -p 8080:8080 \
# and watch the logs to see what went wrong
sudo docker logs -f CONTAINER

When you're done you can stop and remove the container. And remove the image as well.

sudo docker stop mynewcontainer 
sudo docker rm mynewcontainer 
sudo docker image ls
sudo docker image rm user/myimage

And remember: since the original images plone/plone-backend and plone/plone-frontend are already in your system you can create and remove as many containers as you need in seconds.

This thread is amazing.

All of this information on maintaining docker images is exactly where I am in my learning. However, I am also a firm believer in great documentation being the 'one true way' to do things as long as you're on the well beaten path.

With that said, I have two general questions - mostly to improve the Plone Documentation rather than contradict anything in this thread.

Q 1: When should we be using mxdev instead of pip ?

I think that answer is:
A 1: when forking addons or developing your own

But I'm throwing it out there anyway in case I'm wrong.

Q 2: Is it better to edit the docker file for add-ons rather than shell into the docker image?

Q 1: When should we be using mxdev instead of pip ?

mxdev is not a replacement for pip. It is a tool to help create a requirements file that you can use when running pip. I'm aware of 2 specific use cases where it is needed:

  1. You want to use the official Plone constraints.txt file, but override one or two core Plone packages to a newer version to get a recent bugfix.
  2. You want to check out some packages from git, and you want to make sure that if you've made some local changes, they are not accidentally lost when you pip install from a specific branch.

There are more details in Jens Klein's talk about mxdev from ploneconf 2022: Juggling the development of package-rich Python projects with mxdev

Q 2: Is it better to edit the docker file for add-ons rather than shell into the docker image?

Any changes you make while shelled into the running docker container will be lost when the container is removed, UNLESS they are written to a location in the container's filesystem that has been mounted from the host system. Typically that is only data directories. I would only install addons this way if it's for a quick experiment that I intend to throw away.

Creating a Dockerfile to build your own image with your addons and other customizations also has the benefit that you can push the Dockerfile to source control to get built and tested by a continuous integration system.

It gets even worse.

With the frontend image, I wanted to shell in and Change the logo.

I’m sure there is a way to do a “yarn build” and then tell the container’s running npm server to reload, but my old-school skills are not working.

  1. It’s funny to see pid 1 as ‘npm’
  2. npm doesn’t respond to a SIGHUP
  3. A kill 1 did exactly what you would expect, the container exits. (Then refuses to start back up with “port is already in use”)

If this is any hint at all that editing existing running containers is a bad idea….

Time to setup that actual dev environment that creates docker images. It’s a new learning experience, but I’m sure the payoff in devops will be amazing.

See the following note in Docker run reference.

A process running as PID 1 inside a container is treated specially by Linux: it ignores any signal with the default action. As a result, the process will not terminate on SIGINT or SIGTERM unless it is coded to do so.

And the following docker issues #41302, #11065. As well as other issues related to restart policies.