Err: top-level object must be a mapping

My server recently stopped using docker-comose and I had to switch to “docker compose”.
I also had to make some changes to my CI/CD to get it work to my last line:

docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/docker-stack-backend-1040f3996845f955c9874486d3eaeb8339b4fc9c.yml backend

Now I am getting a mapping error, I looked at other topics which could not resolve this. I also upgraded my compose plugin to latest that did not fix it as well.

Deploy Stack:

======CMD======
[docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/docker-stack-backend-1040f3996845f955c9874486d3eaeb8339b4fc9c.yml backend
err: top-level object must be a mapping
======END======

compose file:

version: '3.6'
services:
  db:
    ports:
      - 4545:5432

  pgbackups:
    image: prodrigestivill/postgres-backup-local:12-alpine
    secrets:
      - postgres-password
    volumes:
      - postgres_backup_volume:/backups
    environment:
     - ...
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.labels.${ENVIRONMENT} == true

volumes:
  sqlbak_local_data:
  sqlbak_backups:
  postgres_backup_volume:

You are making the same mistake as in the other topic

Talking about Docker Compose only when you actually use Docker Swam. In the other topic, the original issue at least was related to Docker Compose, but in this case you are using only docker stack commands that is part of Docker Swarm, and not Docker Compose, so I moved the topic to the Docker Swarm category to make it more obvious to everyone. Swarm just let’s you use the compose file syntax but there are differences as you already know.

As I suspected in the other topic as well, I’m still not sure the file you share is actually the one that your pipeline uses. Maybe your original file is changed somehow. You should try to run the commands in a local swarm cluster instead of hunting issues in a pipeline. If it works locally, then the problem is with the pipeline.

This for example:

Is an empty service. Where is the image from which the container has to be started? You should have had an error like this:

failed to create service test_db: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: image reference must be provided

I guess you deleted the parts that seemed irrelevant, but you should remove only passwords keeping the original syntax or it could easily fix the original issue and there is no syntax error anymore in your shared compose file. I can’T even make the syntax wrong. It just runs on my machine. What is the Docker version? I could not find it in the other topic.

Sorry this is the actual compose file, previous file is the ${{ env.OVERRIDE_STACK_FILE }}.

version: "3.6"

services:
  redis:
    image: redis:6
    volumes:
      - redis_volume:/data

  db:
    image: postgres:12
    environment:
      POSTGRES_DB: ...
      POSTGRES_USER: postgres
    volumes:
      - postgres_volume:/var/lib/postgresql/data

  backend: &backend
    image: ${CONTAINER_IMAGE:-backend}
    environment:
      MY_ENVIRONMENT: ${ENVIRONMENT:-dev}
    expose:
      - 5000
    volumes:
      - media_volume/:/app/files

  worker: &worker
    <<: *backend
    command: celery -A my.celery worker --autoscale=8,1 --loglevel=WARNING -B -S redbeat.RedBeatScheduler -Q celery -Ofair
    healthcheck:
      test: echo

  slow-worker:
    <<: *worker
    command: celery -A my.celery worker --autoscale=4,1 --loglevel=WARNING -S redbeat.RedBeatScheduler -Q slow -Ofair

  flower:
    <<: *worker
    command: celery -A my.celery flower
    environment:
      - FLOWER_PERSISTENT=true
      - FLOWER_DB=/flower/db
    volumes:
      - flower_volume:/flower

  media:
    image: flashspys/nginx-static
    volumes:
      - media_volume:/static

  static:
    image: flashspys/nginx-static
    expose:
      - 80
    volumes:
      - static_volume:/static

volumes:
  redis_volume:
  postgres_volume:
  media_volume:
  static_volume:
  flower_volume:

configs:
  backned-config:
    name: ${STACK_NAME:-name}.env
    external: true

PipeLine:

 deploy_production:
    name: Deploy to Production Server
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/heads/release')
    needs:
      - build_and_push
    env:
      IMAGE_ID: ${{ needs.run-tests.outputs.image_id }}

    environment:
      name: Production
      url: https://${{ env.PROD_DOMAIN }}

    steps:
      - name: Git Checkout
        uses: actions/checkout@v2

      - name: Set Envars
        run: |
          echo "STACK_FILE=docker-stack-${{ env.PROD_STACK_NAME }}-${{ github.sha }}.yml" >> $GITHUB_ENV

      - name: Prepare Stack File
        run: >
          ENVIRONMENT=${{ env.PRODUCTION }} DOMAIN=${{ env.PROD_DOMAIN }} CONTAINER_IMAGE=${IMAGE_ID} STACK_NAME=${{ env.PROD_STACK_NAME }}
          docker compose -f ${{ env.DOCKER_COMPOSE_PATH }} -f ${{ env.DOCKER_STACK_PATH }} ${{ env.OVERRIDE_STACK_FILE }}
          config | sed 's/^name:.*/version: "3.6"/' >  ${{ env.STACK_FILE }}

      - name: Move Stack File to Server
        uses: appleboy/scp-action@v0.1.1
        with:
          host: ${{ secrets.PROD_SERVER_ADDR }}
          username: ${{ secrets.PROD_SERVER_USER }}
          key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
          port: ${{ secrets.PROD_SERVER_PORT }}
          source: ${{ env.STACK_FILE }}
          target: "/tmp"

      - name: Deploy Stack
        uses: appleboy/ssh-action@v0.1.4
        with:
          host: ${{ secrets.PROD_SERVER_ADDR }}
          username: ${{ secrets.PROD_SERVER_USER }}
          key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
          port: ${{ secrets.PROD_SERVER_PORT }}
          script: docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/${{ env.STACK_FILE }} ${{ env.PROD_STACK_NAME }}

I don’t see syntax errors so I can only suggest again to

I can share one more idea: Since you replace strings in the deployment file, it is posible that some non-printable characters are added to the file which cannot be handled by Swarm. If it is the case, you can test it by (for testing purposes) adding a static file temporarily to the pipeline which you know worked locally. Then you can compare the files and if both are the same, then you can be sure something adds non-printable characters to the file in your pipeline.

setting up a docker swarm is something I have never done, everything worked fine before. is there a way to just switch to docker-compose.

Then it is time to do so as all you need to do is run

docker swarm init

on a machine where you installed Docker. It can be Docker Desktop

I guess you use swarm for a reason (Docker compose is not for multiple machines). If not, you can replace docker stack commands with docker compose commands. If it requires anything in the pipeline, I still can’t help you with that.

But I am not using multiple servers?! As I mentioned this is some other developers code I had to work with. Obviously going through bunch of tutorials could help but it is urgent to fix this that is why I am here asking questions.
btw when I don’t remove the first line I get this error:
looks like didn’t need to remove the first line

 docker compose -f ${{ env.DOCKER_COMPOSE_PATH }} -f ${{ env.DOCKER_STACK_PATH }} ${{ env.OVERRIDE_STACK_FILE }}
          config >  ${{ env.STACK_FILE }}
service "worker" has neither an image nor a build context specified: invalid compose project

One more reason to try to run a single-node swarm on your machine so you can find out the problem much faster. I enabled swarm on my machine just for you, since it was that easy. But I honestly can’t follow your different issues. I can’t reproduce any of it and that is why the best advice I can give you to simplify the issue so everyone can help you more easily without understanding what happens in the CI/CD pipeline. This is not something I would not do for myself. This is exactly the way I would try to find such an issue. Otherwise we just keep guessing and you keep getting newer and newer error messages that we don’t understand and can’t reproduce.

It doesn’t matter if it worked before. It doesn’t work now, so the task is clear, find out why. And since this is a Docker community forum, we are the best at helping with Docker questions even though you could find someone who already had the same or similar issue, solved it and can share the solution to work in your pipeline.

If you can run docker compose up -d instead of docker stack deploy ..., that is indeed another way to simplify the issue, but it is still better to try it on your local machine and change the pipeline only after that. Just don’t test it using Docker compose locally and keep using swarm in the pipeline.

I ran it locally and it gives me this when doing the docker compose config:

service "backend" refers to undefined volume media_volume/: invalid compose project

The service name change with every command.

compose lines:

  backend: &backend
    image: ${CONTAINER_IMAGE:-backend}
    environment:
      MY_ENVIRONMENT: ${ENVIRONMENT:-dev}
    expose:
      - 5000
    volumes:
      - media_volume/:/app/files
 ...   
volumes:
  redis_volume:
  postgres_volume:
  media_volume:
  static_volume:
  flower_volume:

Does this solve it? I do not want to lose my data:

Lastely:
it looks like removing the slash from “media_volume/” helps but does changing this mess up with my existing volume mapping?