L
L
l4m3r2019-02-11 20:26:24
Docker
l4m3r, 2019-02-11 20:26:24

Are there any best practices on how to organize web project files with docker?

Here, let's say there is a site without docker:

/helloworld
    /app
    /public
    /config
    /vendor
    ...

I need to dockerize it. How to do it better? Just add the docker folder to the site code with configs, Dockerfile, vol database:
/helloworld
    /app
    /public
    /config
    /vendor
    /docker
        /build
        /mysql
    ...
   docker-compose.yml

Or select separately:
/app
    /app
    /public
    /config
    /vendor
    ...
/build
/mysql
docker-compose.yml

Or something else? Any examples of a good project structure?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Maxim Brodsky, 2019-07-09
@l4m3r

It's not so simple, comrade ;)
Following the best practices, you should make a separate repository with a description of the infrastructure of your project.
In total, in your group of projects on GitLab (or in an organization on GitHub) you should get something like the following:

/project-group (organization):
    /api - сюда можно вынести api вашего проекта.
    /desktop - здесь ваш web-проект для desktop на php, например.
    /mobile - здесь ваш web-проект для мобильной версии сайта, на той-же node.js.
    /admin - здесь ваша админка.
    /infrastructure - ну, или назовите проще, "server". Здесь ваши Dockerfile, docker-compose, ci/cd скрипты и т.п.

In order to be able to vary your infrastructure depending on the environment, you must separate the infrastructure repository into separate services. For example, not all project services need to run in a test environment or on a test branch server on subdomains when you make domains like "feature-1.test.project.com" so that your testers can test features in parallel and independently of each other. Also, on dev and / or test environments, you may need to make stub services for external apis that you use. Well, for example, to online payment services for goods on your site, which will always answer "OK" or not "OK".
Therefore, in order to be able to raise an environment with a composition of services different from prod, separation is necessary.
Thus,
/infrastructure
   /api
       service.yml
       build.yml
       deploy.yml
   /mobile
       service.yml
       build.yml
       deploy.yml
   /desktop
       service.yml
       build.yml
       deploy.yml
   /admin
       service.yml
       build.yml
       deploy.yml
   /mysql
       mysql.cnf
       service.yml
   /redis
       redis.conf
       service.yml
   /php-fpm
       Dockerfile
       www-conf
       php.ini
       service.yml
   /nginx
       nginx.conf
       /prod
            site.conf
       /test
            site.conf
       /dev
            site.conf
   /cron
       Dockerfile
       crontab
       service.yml
mobile-dev.sh
desktop-dev.sh
prod.sh
test.sh

In these very *.sh files, which are indicated above, you launch the required composition of services. For example, a developer of a mobile version on react does not have to buy a powerful PC in order to run the entire project on his machine, with mysql, redis, admin and other services. It will be enough for you to build an image of a mobile application, and write something like the following in mobile-dev.sh:
docker-compose -f mobile/service.yml pull;
docker-compose -f mobile/service.yml down;
docker-compose -f mobile/service.yml up --detach;

Well, in mobile/service.yml there might be something like this:
version: "3.7"

services:
  mobile:
    image: keymetrics/pm2:10-alpine
    environment:
      APP_ENV: ${APP_ENV}
      APP_LANG: ${APP_LANG}
      API_URL: ${API_URL}
      BASIC_TOKEN: ${BASIC_TOKEN}
    working_dir: /app
    command: pm2-runtime start config.js --env $APP_ENV
    volumes:
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - ${APP_DIR}:/app
    restart: always
    container_name: mobile

API_URL at the same time, you can land on your test or dev server. Thus, the developer of the mobile version of the site will always have the api version that is actually used in the project. Accordingly, the application code must be able to work with environment variables to configure its settings.
Your site also needs to be launched with a separate service.yml file. Service.yml - can be changed to docker-compose.yml in each service directory, but service looks prettier here.
If you want to raise all services, you need to pass all service.yml files sequentially through the -f flag to your docker-compose. This will be a cumbersome command, which is why separate *.sh files are made to run.
You need to understand that you should not store a Dockerfile in the repository of each project if the presence of an image is required for this project. Not every developer knows how to make Dockerfiles and, for example, install PHP extensions within these Dockerfiles. By delegating responsibility for building the Dockerfile to the project developers, you risk getting a broken service. The best place for a Dockerfile is, in our example, the infrastructure repository held by your DevOps engineers.
The same story with the description of build processes and CI / CD processes. A developer should not be trusted to build his application within a whole huge project infrastructure. To do this, in the infrastructure repository example, there are build.yml/deploy.yml files that describe the assembly and delivery of services. Any CI/CD tools can connect pipeline fragments from external repositories, so when you need to make an autobuild and autodeploy, there will be no problems, because you have already taken into account all the pitfalls of the collaboration of specialists in your company.
The above describes how to correctly implement your project on docker + docker-compose. This does not take into account the presence of swarm-mode or kubernetes, however, this structure will be much easier to use in swarm mode or using kubernetes.
PS. Of course, there are other working practices on this topic;) This one I like the most, and works more universally than the others.

C
chupasaurus, 2019-02-12
@chupasaurus

Turnip content:
In the dockerfile, you prescribe the assembly of the project and mounting the build through multi-stage build , so as not to drag npm/php-composer and so on into the image that you will deploy. Dockerfile example:

FROM: build_image as builder
COPY . /src/app
CD /src/app
RUN "build --output /src/app/build"

FROM: deploy_image
COPY --from=builder /src/app/build /app
WORKDIR /app
//дальше запуск приложения как обычно

D
developer007, 2019-02-11
@developer007

/project1:
    /bin
    /www
    /src (здесь сервисы, контроллеры и тд)
    /docker

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question