2

Directory Structure

build
├── docker-compose.dev.yml
├── playbooks
│   ├── deploy-deps.yml
│   └── setup-local-registry.yml
├── postgres
│   └── DockerFile
└── rabbitmq
    ├── DockerFile
    └── init.sh
deploy-scripts
├── db-schema
│   └── global
│       ├── 01-init.sql
│       ├── 02-tables.sql
│       ├── 03-grant.sql
│       └── 04-index.sql
├── rabbitmq
│   └── global
│       └── prepare-queues.sh

I'm trying to create docker image using ansible. Here is my playbook yml

- hosts: localhost
  vars:
    registry_host: "localhost"
    registry_port: 5000
    i_postgres_image: "orderpostgres"
  tasks:
    - name: "Create & Push Postgres Image"
      docker_image:
        name: "{{ i_postgres_image  }}"
        build:
          path: "../../build/postgres"
        source: build
        state: present
      register: "out"
    - name: Show test output
      debug:
        msg: "{{ out }}"

My Postgres DockerFile

FROM postgres:10.17-buster
COPY ../deploy-scripts/db-schema/global /docker-entrypoint-initdb.d/

When i execute ansible-playbook from the project root directory, this is result of the execution.

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ***********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create & Push Postgres Image] ****************************************************************************************************************************************************************************
changed: [localhost]

TASK [Show test output] ****************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": {
        "actions": [
            "Built image orderpostgres:latest from ../../build/postgres"
        ],
        "changed": true,
        "failed": false,
        "image": null,
        "stdout": "",
        "stdout_lines": []
    }
}

PLAY RECAP *****************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Based on the output I expected the docker image to be built and ready to push to local registry. But when I execute, docker images I'm not seeing that image at all.

docker images
REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
registry     2         b2cb11db9d3d   3 days ago   26.2MB

My analysis until now:

My DockerFile has to copy some scripts from the root path of the project that is the reason it has "../scripts/db-schema". I cannot change this path because the same DockerFile is being used by my docker-compose.dev.yml file inside the build directly for creating dev containers.

I am guessing docker image creation is failing, but ansible module does not throw an error and provides output as success.

Second, ansible docker module does not have config to customize the build context like docker-compose allows in the yml.

Here is my docker-compose.dev.yml for reference

version: '3'
services:
    
  redis:
    image: redis:5.0
    container_name: 'cache'
    ports: 
      - 6379:6379
    volumes: 
      - ~/.docker-volume/redis/data/:/var/lib/redis

  postgres:
    build:
      context: ../
      dockerfile: ./build/postgres/DockerFile
    container_name: 'database'
    restart: always
    environment:
      - POSTGRES_USER=haha
      - POSTGRES_PASSWORD=haha
      - POSTGRES_DB=haha
    logging:
      options: 
        max-size: 10m
        max-file: '3'
    ports: 
      - 5432:5432
    volumes: 
      - ~/.docker-volume/postgres/data/:/var/lib/postgresql/data

My Questions:

  1. How can i solve this problem ? Without rearranging possible and not changing the existing DockerFile
  2. How to configure ansible docker module to the custom context ?
  3. Why is ansible docker module is not throwing error ?

Repro Repo: https://github.com/sathishsoundharajan/ansible-repro

It has files required to reproduce the issue in anyone local

Sathish
  • 2,056
  • 3
  • 26
  • 40
  • @Zeitounator Addressed your review, except for the directory structure part. – Sathish Sep 04 '21 at 17:34
  • 1
    @Zeitounator Addressed directory structure too.. Will follow the same here onwards – Sathish Sep 04 '21 at 17:38
  • 2
    Ansible not returning an error on build is extremely suspicious... Meanwhile the core problem is your `COPY` command in your Dockerfile: you cannot copy files which are out of the build context, i.e. `COPY ../whatever xxx` will never work. – Zeitounator Sep 04 '21 at 17:46
  • 1
    (The `COPY ../...` problem is discussed further in [How to include files outside of Docker's build context?](https://stackoverflow.com/questions/27068596/how-to-include-files-outside-of-dockers-build-context)) – David Maze Sep 04 '21 at 19:27
  • 1
    `ansible docker module does not have config to customize the build context like docker-compose allows` => https://docs.ansible.com/ansible/latest/collections/community/docker/docker_image_module.html#parameter-build/path – Zeitounator Sep 05 '21 at 09:12
  • Yeah @Zeitounator what is the work around ? – Sathish Sep 05 '21 at 09:35
  • What workaround? Create a valid dockerfile and set the same build context and dockerfile for build in each case. – Zeitounator Sep 05 '21 at 12:16
  • @Zeitounator Thank you for the answer, But I don't want to modify the dockerfile, like i said in the question that is valid dockerfile which is already being used by docker-compose.dev.yml.. Why would someone need to create another dockerfile for to work with ansible.. ansible should provide an option to configure the build context Or someother way.. – Sathish Sep 05 '21 at 14:00
  • I don't know from which Dockerfile you think you are building correctly using docker-compose. What I can tell you is that the example Dockerfile in your question will **always** fire an error in whatever situation because as explained in my previous comment, in the other question reported by David Maze, and also in the [documentation](https://docs.docker.com/engine/reference/builder/#copy) => `the path must be inside the context of the build; you cannot COPY ../something /something,...`. **If you don't modify your Dockerfile, you will never get a successful build**. Good luck. – Zeitounator Sep 05 '21 at 14:40
  • @Zeitounator I can able to create docker image and run as container if use the docker-compose.dev.yml file with the command `docker-compose -f build/docker-compose.dev.yml up` – Sathish Sep 05 '21 at 14:51
  • Well then understand why (you think?) it works when it is absolutely impossible it does. There is something you don't see and you are not showing. The example Dockerfile cannot lead to a successful build. Period. If you really don't want to understand that, I have no more refs to propose. And I had miss a part of your last comment but I already provided a link to the option to change the context in ansible. Have a good day. – Zeitounator Sep 05 '21 at 15:17
  • Apologies @Zeitounator .. Here is the repro repo https://github.com/sathishsoundharajan/ansible-repro which you can run your local and reproduce the issue. You can also verify the docker-compose with the current setup working without any change too. Probably i'm missing something obvious here. – Sathish Sep 06 '21 at 17:37
  • 1
    Here is a test which took me about 30 seconds: https://gist.github.com/zeitounator/c55f0acbfafc493b27c2506aae943a83 Please note the last output line: **COPY failed: forbidden path outside the build context: ../deploy-scripts/db-schema/global**. This will be my last reply in this comments thread. – Zeitounator Sep 06 '21 at 20:00

1 Answers1

1

Fixed by doing following changes

postgres/Dockerfile

FROM postgres:10.17-buster
COPY deploy-scripts/db-schema/global /docker-entrypoint-initdb.d/

Ansible Playbook

- hosts: localhost
  vars:
    registry_host: "localhost"
    registry_port: 5000
    i_postgres_image: "order-postgres"
  tasks:
    - name: "Pull & Initialize Postgres Image"
      docker_image:
        name: "{{ i_postgres_image  }}"
        build:
          path: ../../
          dockerfile: build/postgres/Dockerfile
        source: build
        state: present

    - name: "Tag & Push to registry"
      register: "out"
      docker_image:
        name: "{{ i_postgres_image }}"
        repository: "{{ registry_host }}:{{ registry_port }}/{{ i_postgres_image }}"
        push: yes
        source: local

    - name: Show test output
      debug:
        msg: "{{ out }}"
Sathish
  • 2,056
  • 3
  • 26
  • 40